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

开启TS strict模式时,解决@tanstack/react-query useQuery返回数据undefined问题

问题:React Query useQuery 返回数据类型无法收窄为非 undefined

我正在开发一个新项目,Typescript 的 strict linting 规则已设为 true。在此规则下,TypeScript 无法确定 @tanstack/react-query 包中 useQuery 钩子返回数据的类型,它可能是实际类型或 undefined。

相关代码

hooks/useFiles.ts

import { useQuery } from '@tanstack/react-query';
import { fileApi } from '@/utils/apiClient';
import { ListFileResponse } from '@types/files';

type useFilesProps = {
    page?: number;
    limit?: number;
};

export const useFiles = ({ page = 1, limit = 20 }: useFilesProps ) => {
    return useQuery<ListFileResponse>({
        queryKey: ['files'],
        queryFn: () => fileApi.listFiles({ page, limit }).then((res) => res.data),
    });
};

views/fileOverview.ts

export const FileOverview = () => {
    const { data: fileData } = useFiles({ page, limit });

    console.log(fileData);
    // ...
};

此处 fileData 的类型为 ListFileResponse | undefined。

即使添加了 isLoading 和 isError 的检查,结果仍然相同:

const { data: fileData, isLoading: isFileLoading, isError: isFileError } = useFiles({ page, limit });

if (isFileLoading) return <p>Loading</p>;
if (isFileError) return <p>Error</p> ;

console.log(fileData); // 类型仍为 ListFileResponse | undefined

请问需要进行哪些额外检查,才能让 TypeScript linting 确信 fileData 不是 undefined?


解决方案

以下几种方法可以让 TypeScript 确认 fileData 非 undefined:

  • 利用 isSuccess 状态守卫:React Query 提供的 isSuccess 状态会在查询成功且数据已加载时为 true,TypeScript 能识别这个状态的类型关联,此时 data 会自动收窄为非 undefined 类型:
const { data: fileData, isLoading: isFileLoading, isError: isFileError, isSuccess } = useFiles({ page, limit });

if (isFileLoading) return <p>Loading</p>;
if (isFileError) return <p>Error</p> ;
if (!isSuccess) return null; // 兜底处理其他未覆盖的状态

console.log(fileData); // 此时类型为 ListFileResponse
  • 直接检查数据存在性:通过简单的存在性判断(如 fileData 或 fileData !== undefined),可以让 TypeScript 自动收窄类型:
const { data: fileData, isLoading: isFileLoading, isError: isFileError } = useFiles({ page, limit });

if (isFileLoading) return <p>Loading</p>;
if (isFileError) return <p>Error</p> ;
if (!fileData) return <p>No data available</p>;

console.log(fileData); // 类型收窄为 ListFileResponse
  • 配置 initialData:如果查询场景允许设置初始数据,可以在 useQuery 中指定 initialData,这样 data 的类型会自动排除 undefined:
// 修改 hooks/useFiles.ts
export const useFiles = ({ page = 1, limit = 20 }: useFilesProps ) => {
    return useQuery<ListFileResponse>({
        queryKey: ['files'],
        queryFn: () => fileApi.listFiles({ page, limit }).then((res) => res.data),
        initialData: [] as ListFileResponse, // 根据实际业务设置合理初始值
    });
};
  • 非空断言(谨慎使用):如果你能完全确保数据一定存在(比如后端接口绝不会返回空),可以用非空断言操作符 ! 强制标记数据非 undefined,但这种方式会跳过 TypeScript 的类型检查,仅建议在逻辑绝对安全时使用:
console.log(fileData!); // 强制类型为 ListFileResponse

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:38:11