TypeScript中如何封装带isLoading状态的类型合法的useSWR自定义Hook?
问题根源
你的问题核心在于SWRHook是调用层泛型的函数类型,而非类型层泛型:它的泛型参数<Data, Error>是绑定在函数调用时机的,不是定义SWRHook类型时传入的。所以直接使用Parameters<SWRHook>时,TS无法推断泛型参数,自然返回never类型。
解决方案
直接给自定义Hook声明和原生useSWR对齐的调用层泛型即可,以下是最简可运行实现:
import useSWR, { SWRResponse, type SWRConfiguration, type Key, type Fetcher } from 'swr'; // 加载状态判断工具函数 const isLoading = ({ data, error }: SWRResponse<any, any>): boolean => { return data === undefined && error === undefined; }; // 扩展返回值类型定义 type SWRResponseWithLoading<Data = any, Error = any> = SWRResponse<Data, Error> & { isLoading: boolean; }; // 自定义Hook实现,泛型放在函数签名前,和原生useSWR对齐 function useSWRWithLoading<Data = any, Error = any>( key: Key, fetcher?: Fetcher<Data> | null, config?: SWRConfiguration<Data, Error> ): SWRResponseWithLoading<Data, Error> { const swrResponse = useSWR(key, fetcher, config); return { ...swrResponse, isLoading: isLoading(swrResponse) }; } // 如果需要完全兼容原生useSWR的所有参数重载,可以用以下更通用的写法,不需要手动枚举参数 const useSWRWithLoadingGeneric = (<Data = any, Error = any>(...args: Parameters<typeof useSWR<Data, Error>>) => { const swrResponse = useSWR(...args); return { ...swrResponse, isLoading: isLoading(swrResponse) }; }) as <Data = any, Error = any>(...args: Parameters<typeof useSWR<Data, Error>>) => SWRResponseWithLoading<Data, Error>;
效果验证
使用时完全和原生useSWR一致,自动推断返回的data类型,且能正确识别isLoading字段:
// 示例使用 const { data, error, isLoading } = useSWRWithLoading<User>('/api/user', fetcher); // data 类型为 User | undefined // isLoading 类型为 boolean
内容的提问来源于stack exchange,提问作者Xander
相关产品推荐
相关产品推荐

