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, });
核心问题
你当前的写法存在两个关键问题:
- 泛型
T的约束T extends UserResponseDto过于严格,强制select返回值必须是单个UserResponseDto或其子类型,但queryFn原本返回的是数组类型,当不传select时,TypeScript无法正确推断T的默认类型,只能 fallback到约束的UserResponseDto,导致data类型不符合预期。 - 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
相关产品推荐
相关产品推荐

