我想实现一个 ts 版本的简版 usePromise
// 期望类型推导出:data 的类型是 {list: FileNode[]} (即返回 T)
const [data, isOk] = usePromise(
() => {
return Promise.resolve({list:[]}) as Promise<{ list: FileNode[] }>;
},
{ initValue: {list:[]} }
);
// 期望类型推导出:fileNodes 的类型是一个 FileNode 数组 (即返回 T['list'])
const [fileNodes, isOk] = usePromise(
() => {
return Promise.resolve({list:[]}) as Promise<{ list: FileNode[] }>;
},
{ initValue: [] },
"list",
);
我的 usePromise 实现如下, 利用K extends keyof T
判断如果 K 属性存在就返回T[K]
, 否则返回T
测试发现 ts 判断可选参数时总会失败,只会返回T
.
export function usePromise<T, K>(
factory: () => Promise<T>,
options: Options<K extends keyof T ? T[K] : T> = {},
filterKey?: K,
): [K extends keyof T ? T[K] : T, boolean] {
type R = K extends keyof T ? T[K] : T;
const [state, setState] = useState<R>(
options.initValue!,
);
const isLoadingRef = useRef(false);
useEffect(() => {
factory().then((r) => {
if (filterKey) {
setState((r as any)[filterKey] as unknown as R);
} else {
setState(r as unknown as R);
}
}).catch((res) => {
if (options.onError) options.onError(res);
else throw res;
});
}, []);
return [state, isLoadingRef.current] as [R, boolean];
}
我知道可以增加两个 function 的类型重载解决这个问题,但是手写一遍类型重载感觉太麻烦。
请教一下有没有更简单的方法呢?
1
YuJianrong 2022-09-15 08:47:03 +08:00 1
|
2
YuJianrong 2022-09-15 08:52:04 +08:00 1
|
3
a132811 OP @YuJianrong 不是纠结范型。只是想找一个比 overloaded 更简单的方法。
在 statckoverflow 我找到答案啦: https://stackoverflow.com/questions/73718892/return-different-generic-type-via-functions-optional-argument-in-typescript |