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

在TypeScript中如何为带响应拦截器的Axios搭配useSWR Fetcher正确编写类型?

在TypeScript中如何为带响应拦截器的Axios搭配useSWR Fetcher正确编写类型?

嘿,这个问题我之前在项目里踩过一模一样的坑!因为Axios默认的类型体系是围绕返回AxiosResponse<T>设计的,但咱们的响应拦截器直接返回了response.data,这就打破了原本的类型约定,导致useSWR没法正确推断接口返回的数据类型。咱们一步步来把它搞定:

第一步:给Axios实例重新定义匹配拦截器的类型

首先,我们需要修改Axios实例的类型,让它的所有请求方法(比如get、post、request)直接返回数据类型T,而不是默认的AxiosResponse<T>。

// api.ts
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";

export const options = {
  baseURL: process.env.API_ORIGIN || "http://localhost:8080",
  withCredentials: true,
};

// 自定义Axios实例类型,覆盖所有请求方法的返回值
type CustomAxiosInstance = {
  [K in keyof AxiosInstance]: AxiosInstance[K] extends <T = any>(...args: any[]) => Promise<AxiosResponse<T>>
    ? <T = any>(...args: Parameters<AxiosInstance[K]>) => Promise<T>
    : AxiosInstance[K];
};

// 创建实例并断言为我们自定义的类型
const API = axios.create(options) as CustomAxiosInstance;

// 完善你的响应拦截器(补全错误处理逻辑)
API.interceptors.response.use(
  (response) => response.data, // 直接返回数据,和我们的自定义类型完全匹配
  (error) => {
    // 这里可以统一处理错误,比如返回更友好的自定义错误结构
    return Promise.reject(error.response?.data || error.message);
  }
);

export default API;

第二步:编写类型安全的useSWR Fetcher

有了类型正确的Axios实例后,我们就可以基于它创建一个符合useSWR要求的fetcher,同时给fetcher加上明确的类型约束:

// 可以把这个fetcher放在api.ts或者单独的swr-utils.ts文件里
import API from "./api";
import { AxiosRequestConfig } from "axios";

// 定义fetcher的通用类型:接收url和可选配置,返回对应数据的Promise
type SWRFetcher = <T = any>(url: string, config?: AxiosRequestConfig) => Promise<T>;

// 实现基础的GET请求fetcher
export const fetcher: SWRFetcher = async (url, config = {}) => {
  return API.get(url, config);
};

// 如果你需要支持多种请求方法(比如POST、PUT),可以写更灵活的fetcher:
export const flexibleFetcher = async <T = any>(
  args: [string, AxiosRequestConfig?] | string,
  config?: AxiosRequestConfig
): Promise<T> => {
  const [url, reqConfig] = Array.isArray(args) ? args : [args, {}];
  return API.request<T>({ url, ...reqConfig, ...config });
};

第三步:在useSWR中使用类型安全的fetcher

现在你在组件里使用useSWR时,就能让TypeScript正确推断数据类型了,也可以手动指定返回数据的类型,获得完整的代码提示:

import useSWR from "swr";
import { fetcher } from "./api";

// 先定义接口返回的数据类型
type UserProfile = {
  id: number;
  username: string;
  email: string;
  avatarUrl: string;
};

const UserProfileComponent = () => {
  // 手动指定数据类型,TypeScript会自动校验fetcher的返回值是否匹配
  const { data: userProfile, error } = useSWR<UserProfile>("/api/user/profile", fetcher);

  if (error) return <div>加载失败:{error}</div>;
  if (!userProfile) return <div>加载中...</div>;

  // 这里userProfile会被正确推断为UserProfile类型,所有属性都有类型提示
  return (
    <div>
      <h1>{userProfile.username}</h1>
      <p>邮箱:{userProfile.email}</p>
    </div>
  );
};

可选:给错误也加上类型

如果你的拦截器返回了自定义的错误结构,也可以给错误指定类型,让useSWR的error也有精准的类型提示:

// 定义自定义错误类型
type ApiError = {
  code: number;
  message: string;
  details?: string[];
};

// 修改拦截器的错误处理,确保返回的是ApiError格式
API.interceptors.response.use(
  (response) => response.data,
  (error) => {
    const apiError: ApiError = {
      code: error.response?.status || 500,
      message: error.response?.data?.message || error.message,
      details: error.response?.data?.details,
    };
    return Promise.reject(apiError);
  }
);

// 然后在useSWR中同时指定数据和错误类型
const { data: userProfile, error } = useSWR<UserProfile, ApiError>("/api/user/profile", fetcher);

// 此时error会被推断为ApiError | undefined,访问error.code、error.message都有类型提示

这样一套下来,你的Axios实例、fetcher和useSWR的使用就都有完整的TypeScript类型支持了,不会再出现类型不匹配的警告或者错误。

备注:内容来源于stack exchange,提问作者Winfrey De Vera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 17:28:06