我想实现一个 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 ![]() |
2 YuJianrong 2022-09-15 08:52:04 +08:00 ![]() |
3 a132811 OP @YuJianrong 不是纠结范型。只是想找一个比 overloaded 更简单的方法。 在 statckoverflow 我找到答案啦: https://stackoverflow.com/questions/73718892/return-different-generic-type-via-functions-optional-argument-in-typescript |