我想实现一个 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 的类型重载解决这个问题,但是手写一遍类型重载感觉太麻烦。
请教一下有没有更简单的方法呢?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.