如何让TypeScript编译器识别React-Query中已存在的数据?
解决React Query中TypeScript无法识别data已存在的问题
这个问题确实是React Query结合TypeScript开发时的常见痛点——虽然React Query保证了isLoading、isError这类状态的稳定性和互斥性,但TypeScript的类型系统没办法自动识别这种业务逻辑上的状态依赖,所以会固执地认为data可能还是undefined。下面是几种靠谱的解决方式:
1. 使用非空断言运算符(!)
这是最直接的方案,因为我们已经通过isLoading和isError的分支处理,完全排除了data不存在的场景,所以可以安全地用!告诉TypeScript:“我确定这里的data不是undefined”。
修改你的代码如下:
function Todos() { const { isLoading, isError, data, error } = useQuery('todos', fetchTodoList) if (isLoading) { return <span>Loading...</span> } if (isError) { return <span>Error: {error.message}</span> } // 用!断言data非空 return ( <ul> {data!.map(todo => ( <li key={todo.id}>{todo.title}</li> ))} </ul> ) }
2. 添加额外的空值检查(适合严谨派)
如果你不想用非空断言(担心后续逻辑变更导致断言失效),可以加一个冗余但TypeScript认可的空值检查。虽然从业务逻辑上看这一步多余,但能让TypeScript彻底放心data的存在:
function Todos() { const { isLoading, isError, data, error } = useQuery('todos', fetchTodoList) if (isLoading) { return <span>Loading...</span> } if (isError) { return <span>Error: {error.message}</span> } // 额外检查data是否存在 if (!data) { return <span>No todos found</span>; // 或者返回其他fallback组件 } // 此时TypeScript已确认data非空 return ( <ul> {data.map(todo => ( <li key={todo.id}>{todo.title}</li> ))} </ul> ) }
3. 显式指定useQuery的泛型类型
如果你的fetchTodoList返回的是明确的非空类型(比如总是返回数组,哪怕是空数组),可以给useQuery指定泛型,让TypeScript更清楚data的类型结构,再结合前面的状态检查,也能减少类型报错:
// 先定义Todo类型 interface Todo { id: number; title: string; } function Todos() { // 明确指定useQuery的泛型:返回数据类型、错误类型 const { isLoading, isError, data, error } = useQuery<Todo[], Error>('todos', fetchTodoList) if (isLoading) { return <span>Loading...</span> } if (isError) { return <span>Error: {error.message}</span> } // 结合泛型和状态检查,再用!断言更稳妥 return ( <ul> {data!.map(todo => ( <li key={todo.id}>{todo.title}</li> ))} </ul> ) }
整体来说,第一种方案是React Query官方文档更偏向的方式,因为它利用了React Query的状态保证,代码简洁且不会引入冗余逻辑。
内容的提问来源于stack exchange,提问作者Xen_mar
相关产品推荐
相关产品推荐

