TypeScript 泛型与工具类型实战:企业级通用数据请求封装完整案例
一、文档概述
在前端项目开发中,网络请求是高频基础能力。传统JavaScript封装的请求函数存在类型缺失、参数与返回值无校验、复用性差等问题。TypeScript凭借泛型实现类型复用,结合内置工具类型约束参数、过滤字段、规范返回结构,可打造出类型安全、可拓展、适配企业级业务的通用请求工具。本文基于Axios,结合TS泛型、常用工具类型完成通用请求封装,并讲解核心知识点与落地用法。
二、前置依赖
项目需安装基础依赖,执行以下命令:
npm install axios typescript @types/axios -S
三、核心类型定义
首先定义请求基础枚举、通用接口,使用Partial、Required、Pick等TS工具类型约束配置项,统一请求格式。
// 请求方法枚举
export enum RequestMethod {
GET = "GET",
POST = "POST",
PUT = "PUT",
DELETE = "DELETE"
}
// 基础请求配置
interface BaseRequestConfig {
url: string;
method: RequestMethod;
timeout?: number;
headers?: Record<string, string>;
}
// 使用工具类型:必填请求核心字段,可选拓展字段
type FullRequestConfig = Required<Pick<BaseRequestConfig, "url" | "method">> & Partial<Omit<BaseRequestConfig, "url" | "method">>;
// 统一后端返回格式
export interface ApiResponse<T> {
code: number;
message: string;
data: T;
success: boolean;
}
知识点说明:
Required:将接口所有可选属性转为必选;Pick:从类型中挑选指定属性生成新类型;Omit:剔除类型中指定属性;Partial:将接口所有必选属性转为可选。
四、通用请求函数封装
利用泛型 <T> 动态约束接口返回data的类型,实现不同接口独立类型校验,同时统一拦截器、超时、异常处理逻辑。
import axios, { AxiosRequestConfig, AxiosError } from "axios";
// 创建axios实例
const service = axios.create({
baseURL: "/api",
timeout: 10000
});
// 请求拦截器
service.interceptors.request.use(
(config) => {
// 统一添加Token
config.headers.Authorization = `Bearer ${localStorage.getItem("token") || ""}`;
return config;
},
(error: AxiosError) => Promise.reject(error)
);
// 响应拦截器
service.interceptors.response.use(
(res) => res.data,
(error: AxiosError) => {
console.error("请求异常:", error.message);
return Promise.reject(error);
}
);
/**
* 通用请求函数(泛型实现类型动态匹配)
* @param config 请求配置
* @returns 后端结构化返回数据
*/
export function request<T>(config: FullRequestConfig): Promise<ApiResponse<T>> {
const axiosConfig: AxiosRequestConfig = {
url: config.url,
method: config.method,
timeout: config.timeout,
headers: config.headers
};
return service(axiosConfig);
}
五、业务接口调用演示
基于封装的通用请求函数,模拟用户查询、新增用户两个业务接口,演示泛型在实际业务中的使用,全程拥有完整代码提示与类型校验。
// 定义用户实体类型
export interface UserInfo {
id: number;
username: string;
age: number;
phone: string;
}
// 1. 获取用户详情接口
async function getUserDetail(userId: number) {
// 泛型指定返回data为UserInfo类型
const res = await request<UserInfo>({
url: `/user/detail?id=${userId}`,
method: RequestMethod.GET
});
if (res.success) {
console.log("用户信息:", res.data.username, res.data.age);
}
}
// 2. 新增用户接口
async function addUser(user: Omit<UserInfo, "id">) {
const res = await request<boolean>({
url: "/user/add",
method: RequestMethod.POST,
headers: {
"Content-Type": "application/json"
}
});
if (res.success && res.data) {
console.log("新增用户成功");
}
}
// 调用测试
getUserDetail(1);
addUser({ username: "test", age: 22, phone: "13800138000" });
核心亮点:调用接口时通过泛型<T>绑定业务类型,编辑器可自动提示字段,编译阶段即可发现参数、返回值类型错误,规避线上BUG。
六、总结
- 泛型解决了请求函数类型复用问题,让不同接口拥有独立类型约束,告别
any滥用; - TypeScript工具类型可灵活裁剪、改造配置类型,简化重复类型编写,统一项目类型规范;
- 基于Axios+TS封装的通用请求,兼顾统一性、安全性与拓展性,完全适配中大型企业前端项目。
该方案可在此基础上拓展文件上传、分页请求、请求防抖等功能,整体架构稳定且易维护。
海量精选技术文档和实战案例持续更新,敬请关注【风骏时光少年】