You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 06:02:51