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

React Query useQuery选择器泛型定义及无选择器时类型异常问题

问题分析与解决方案

问题代码

export const useAllUsers = <T extends UserResponseDto>(
  select?: (data: UserResponseDto[]) => T
) =>
  useQuery<UserResponseDto[], ErrorResponse, T, string[]>({
    queryKey: [QueryClientKeys.GET_ALL_USERS],
    queryFn: async () => {
      const response = await ApiService.getAllUsers();
      return response.data;
    },
    select: select,
    staleTime: Infinity,
    cacheTime: Infinity,
    retry: false,
  });

核心问题

你当前的写法存在两个关键问题:

  1. 泛型T的约束T extends UserResponseDto过于严格,强制select返回值必须是单个UserResponseDto或其子类型,但queryFn原本返回的是数组类型,当不传select时,TypeScript无法正确推断T的默认类型,只能 fallback到约束的UserResponseDto,导致data类型不符合预期。
  2. useQuery的第三个泛型参数(select后的返回类型)固定为T,但未给T设置合理的默认值,加剧了无select时的类型推断错误。

修复方案

调整泛型定义,给T设置默认值为UserResponseDto[],同时根据需求放松泛型约束:

// 允许select返回任意类型,默认返回原数组
export const useAllUsers = <T = UserResponseDto[]>(
  select?: (data: UserResponseDto[]) => T
) =>
  useQuery<UserResponseDto[], ErrorResponse, T, string[]>({
    queryKey: [QueryClientKeys.GET_ALL_USERS],
    queryFn: async () => {
      const response = await ApiService.getAllUsers();
      return response.data;
    },
    select: select,
    staleTime: Infinity,
    cacheTime: Infinity,
    retry: false,
  });

如果需要限制select返回值必须和用户数据相关,也可以把泛型约束调整为:

<T extends UserResponseDto | UserResponseDto[] = UserResponseDto[]>

效果验证

  • 不传select调用useAllUsers()时,data类型自动推断为UserResponseDto[],符合预期。
  • 传入select函数(比如select: (users) => users[0])时,data类型自动推断为UserResponseDto,类型逻辑正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:08:14