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

TypeScript中使用function.apply调用Axios时传递泛型的方法

解决方案

你不需要移除封装的requestWrapper,通过以下方式可以给它添加泛型支持,同时保留对Axios方法的动态调用能力:

思路1:适配Axios方法参数,直接调用泛型方法

Axios的get/post等核心方法本身就是泛型函数,我们可以让requestWrapper作为泛型函数,根据HTTP方法的参数差异直接调用对应方法并传递泛型参数:

import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';

// 限定支持的HTTP方法,避免传入无效方法名
type HttpMethod = 'get' | 'delete' | 'post' | 'put' | 'patch';

/**
 * 泛型请求封装函数
 * @template T 响应数据的类型
 * @param method HTTP请求方法
 * @param url 请求地址
 * @param dataOrConfig 请求体(仅post/put/patch用)或请求配置
 * @param config 请求配置(仅post/put/patch用)
 * @returns 带类型化响应的Promise
 */
function requestWrapper<T = any>(
  method: HttpMethod,
  url: string,
  dataOrConfig?: any,
  config?: AxiosRequestConfig
): Promise<AxiosResponse<T>> {
  // 针对带请求体的方法,传递url + data + config
  if (['post', 'put', 'patch'].includes(method)) {
    return axios[method]<T>(url, dataOrConfig, config);
  }
  // 针对无请求体的方法,传递url + config
  return axios[method]<T>(url, dataOrConfig as AxiosRequestConfig);
}

// 使用示例:定义响应数据类型
interface User {
  id: number;
  name: string;
  email: string;
}

// GET请求,响应数据为User数组
requestWrapper<User[]>('get', '/api/users').then(res => {
  // res.data自动推断为User[]类型,支持类型提示
  console.log(res.data[0].name);
});

// POST请求,响应数据为单个User
requestWrapper<User>('post', '/api/users', { name: 'Alice', email: 'alice@example.com' }).then(res => {
  console.log(res.data.id);
});

思路2:保留apply调用,通过类型断言绑定泛型

如果你的requestWrapper依赖apply处理复杂参数逻辑,可以通过类型断言将Axios方法转为泛型函数,再指定泛型参数:

import axios, { AxiosResponse } from 'axios';

// 提取Axios支持的泛型方法类型
type AxiosGenericMethod = <T>(...args: any[]) => Promise<AxiosResponse<T>>;

// 限定支持的HTTP方法
type HttpMethod = keyof Pick<typeof axios, 'get' | 'delete' | 'post' | 'put' | 'patch'>;

function requestWrapper<T = any>(
  method: HttpMethod,
  ...args: Parameters<typeof axios[HttpMethod]>
): Promise<AxiosResponse<T>> {
  // 将Axios方法断言为泛型方法,再指定T
  const genericMethod = axios[method] as AxiosGenericMethod;
  // 用apply调用(也可以直接用扩展运算符...args)
  return genericMethod.apply(axios, args) as Promise<AxiosResponse<T>>;
}

// 使用示例
interface Article {
  id: string;
  title: string;
}

requestWrapper<Article>('get', '/api/articles/1').then(res => {
  console.log(res.data.title);
});

为什么不建议移除wrapper?

封装requestWrapper的核心价值是统一处理请求逻辑(比如全局错误拦截、请求头注入、日志上报等),如果直接在业务代码中调用Axios,后续要更换HTTP客户端(比如换成fetch、Ky)时,需要修改所有业务代码,违背了封装的初衷。通过上述改造,既保留了封装的优势,又获得了TypeScript的类型安全支持。

内容的提问来源于stack exchange,提问作者Jesús Imitola

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 05:55:30