使用TypeScript与React Query时的类型推断难题
解决React Query解构重命名后的TypeScript类型推断问题
当你解构重命名React Query钩子返回的字段后,TypeScript会丢失isSuccess(即你重命名的loaded)与data(即stuff)之间的类型关联,导致无法自动推断loaded为true时stuff一定非undefined。以下是几种可行的解决办法:
方法1:使用自定义类型守卫
手动编写类型守卫函数,明确关联loaded和stuff的类型关系:
// 定义类型守卫 function isStuffLoaded( props: { loaded: boolean; stuff: string[] | undefined } ): props is { loaded: true; stuff: string[] } { return props.loaded && props.stuff !== undefined; } // 组件中使用 const { data: stuff, isLoading, isSuccess: loaded } = useStuff(); if (isStuffLoaded({ loaded, stuff })) { // 此时TypeScript能正确推断stuff为string[]类型 return <Stuff items={stuff} />; }
方法2:改造自定义钩子,返回判别联合类型
直接在自定义钩子中返回带判别式的联合类型,让TypeScript自动识别类型关联:
// 定义useStuff的返回类型 type UseStuffResult = | { loaded: false; stuff: undefined; isLoading: boolean } | { loaded: true; stuff: string[]; isLoading: false }; // 改造自定义钩子 function useStuff(): UseStuffResult { const { data, isLoading, isSuccess } = useQuery({ queryKey: ['stuff'], queryFn: () => fetch('/api/stuff').then(res => res.json()), }); // 断言返回类型,确保类型匹配 return { loaded: isSuccess, stuff: data, isLoading, } as UseStuffResult; } // 组件中使用 const { stuff, loaded, isLoading } = useStuff(); if (loaded) { // TypeScript自动推断stuff为string[] return <Stuff items={stuff} />; }
方法3:临时保留原对象的类型关联(快速方案)
如果不想修改钩子或写类型守卫,可以在判断时临时引用原钩子返回对象的isSuccess,而非重命名后的loaded:
const queryResult = useStuff(); const { data: stuff, isLoading } = queryResult; if (queryResult.isSuccess) { return <Stuff items={stuff} />; }
方法4:非空断言(不推荐)
若你能100%保证loaded为true时stuff一定存在,可以用非空断言跳过类型检查,但这种方法会丢失TypeScript的类型安全保障,仅建议在逻辑绝对可靠的场景使用:
const { data: stuff, isSuccess: loaded } = useStuff(); if (loaded) { return <Stuff items={stuff!} />; }
内容的提问来源于stack exchange,提问作者ChambreNoire
相关产品推荐
相关产品推荐

