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

React Query中useQuery赋值后回调内类型收窄失效问题

React Query中useQuery数据赋值后的类型收窄问题

在React Query里,useQuery返回的data类型是T | undefined,直接对data做类型收窄时TypeScript能正常识别,但把data赋值给另一个变量后,在回调函数里对该变量的类型收窄会失效——比如在map这类回调里,变量仍被判定为T | undefined。

代码示例

const { data } = useQuery<number[]>("test", () => [1, 2, 3, 4]);

let data2 = data;
// 此处对data2做过滤、排序等处理...

const fun0 = () => {
  if (!data) return;

  // 无类型错误
  [1, 2, 3].map((one) => data[0]);
};

const fun = () => {
  if (!data2) return;

  // 此处正常,data2被识别为number[]
  const foo = data2[0];

  // 类型错误:data2仍被判定为number[] | undefined
  [1, 2, 3].map((one) => data2[0]);
};

问题原因

TypeScript对const和let的类型跟踪逻辑不同:

  • useQuery返回的data是const声明的,TypeScript能确定它的引用不会被篡改,所以在if (!data)判断后,后续所有对data的引用都会被认定为非undefined,包括回调内部。
  • 而let data2 = data是可变变量,TypeScript无法保证在if (!data2)判断结束后、回调执行前,data2不会被重新赋值为undefined,因此在回调里不会认可之前的类型收窄结果。

解决方案

方案1:改用const声明变量

如果后续不需要修改data2,直接用const替代let,TypeScript就能正常跟踪其类型:

const data2 = data; // 替换let为const

方案2:收窄后存入常量再使用

如果必须用let(比如需要修改data2),可以在类型收窄后把值存入一个const变量,后续回调里使用这个常量:

const fun = () => {
  if (!data2) return;
  const safeData = data2; // safeData被推断为number[]
  [1, 2, 3].map((one) => safeData[0]); // 无类型错误
};

方案3:类型断言(不推荐)

如果能确保data2在回调执行时一定非undefined,可以用类型断言强制指定类型,但这种方式会跳过TypeScript的类型检查,存在风险:

[1, 2, 3].map((one) => (data2 as number[])[0]);

内容的提问来源于stack exchange,提问作者Xun Yang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 04:40:25