自定义Hook中useQuery返回useQueryResults<unknown,unknown>类型问题
自定义Hook useGetQuery返回数据类型为unknown的解决方法
问题场景
我写了一个带页面聚焦重取功能的自定义Hook useGetQuery,代码如下:
type Props = Parameters<typeof useQuery>; const useGetQuery = (...params: Props) => { const useQueryResults = useQuery(params); useFocusEffect( React.useCallback(() => { useQueryResults.refetch(); }, [useQueryResults]) ); return useQueryResults; };
接着在useGetScreen中调用这个Hook:
export const useGetScreen = (screenId: string) => { return useGetQuery(['getScreen', { screenId }], () => getScreen(screenId), { staleTime: 0 }); };
但调用const { data: screen } = useGetScreen('vegetables');时,screen的类型变成了unknown,而直接使用useQuery时TypeScript能自动推断类型。
问题原因
useQuery是泛型函数,它的返回类型依赖于传入的查询函数的返回值类型。但当前useGetQuery只是简单接收Parameters<typeof useQuery>作为参数,既没有保留useQuery的泛型信息,还错误地将参数数组直接传给useQuery(useQuery接收多个独立参数而非单个数组),双重原因导致TypeScript无法自动推导出返回数据的具体类型,只能默认设为unknown。
解决方案
让useGetQuery继承useQuery的泛型参数,并修正参数传递方式,确保类型信息能正确传递:
import { useQuery, QueryKey, UseQueryOptions, UseQueryResult } from '@tanstack/react-query'; import { useFocusEffect } from '@react-navigation/native'; import React from 'react'; const useGetQuery = < TQueryKey extends QueryKey, TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TContext = unknown >( ...params: Parameters<typeof useQuery<TQueryKey, TQueryFnData, TError, TData, TContext>> ): UseQueryResult<TData, TError> => { const queryResult = useQuery(...params); // 展开参数,而非直接传数组 useFocusEffect( React.useCallback(() => { queryResult.refetch(); }, [queryResult]) ); return queryResult; };
修改后,useGetScreen会自动继承getScreen(screenId)的返回类型,调用useGetScreen时screen就能获得正确的类型了。
简化版写法
如果不需要精细控制泛型参数,也可以用更简洁的方式复用useQuery的类型:
import { useQuery, UseQueryOptions, UseQueryResult } from '@tanstack/react-query'; import { useFocusEffect } from '@react-navigation/native'; import React from 'react'; const useGetQuery = <TData = unknown, TError = unknown>( queryKey: unknown[], queryFn: () => Promise<TData>, options?: Omit<UseQueryOptions<TData, TError>, 'queryKey' | 'queryFn'> ): UseQueryResult<TData, TError> => { const result = useQuery(queryKey, queryFn, options); useFocusEffect( React.useCallback(() => { result.refetch(); }, [result]) ); return result; };
内容的提问来源于stack exchange,提问作者Onyx
相关产品推荐
相关产品推荐

