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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 16:57:00