Axios+Typescript请求时如何给返回数据添加判别器转为可辨识联合类型
TypeScript 泛型仅作用于编译期的类型校验,不会生成任何运行时代码,因此你直接通过
client.get<UnionTypeA>传递的类型标注,无法自动给实际返回的响应数据追加discriminator字段,这就是你运行时该字段为undefined的核心原因。
方案1:封装带判别器注入的请求方法
这种方案灵活性最高,不需要提前做路径映射,调用时手动传入对应判别器即可,适合路径和判别器没有固定对应关系的场景。
首先是基础类型定义和封装代码:
import axios, { AxiosRequestConfig } from 'axios'; // 可辨识联合基础泛型 type DiscriminatedResult<Discriminator extends string, Data = {}> = Data & { discriminator: Discriminator; }; // 你的业务类型定义 type TypeA = { prop1: number; prop2: number; }; type UnionTypeA = DiscriminatedResult<'A', TypeA>; type TypeB = { prop3: string; prop4: boolean; }; type UnionTypeB = DiscriminatedResult<'B', TypeB>; const client = axios.create(); // 封装自定义get方法,调用时传入判别器 async function getWithDiscriminator<D extends string, T>( url: string, discriminator: D, config?: AxiosRequestConfig ): Promise<DiscriminatedResult<D, T>> { const res = await client.get<T>(url, config); // 运行时主动注入判别器字段 return { ...res.data, discriminator }; }
调用示例:
const data = await getWithDiscriminator<'A', TypeA>('example/api/url', 'A'); // 运行时已存在discriminator字段,TS也可以正常识别类型 if (data.discriminator === 'A') { console.log(data.prop1); // 无类型报错 }
方案2:Axios响应拦截器统一注入
如果请求路径和判别器有固定的对应关系,你可以直接用拦截器批量处理,不需要修改业务侧的调用代码:
import axios from 'axios'; const client = axios.create(); // 配置路径和对应判别器的映射表 const pathDiscriminatorMap: Record<string, string> = { 'example/api/url': 'A', 'example/api/other': 'B' }; // 响应拦截器统一注入判别器 client.interceptors.response.use(res => { const discriminator = pathDiscriminatorMap[res.config.url || '']; if (discriminator) { res.data = { ...res.data, discriminator }; } return res; });
调用时直接用原有写法即可:
const res = await client.get<UnionTypeA>('example/api/url'); console.log(res.data.discriminator); // 运行时值为'A'
注意事项
- 如果同一个接口返回的内容对应多种判别器类型,你可以在封装方法或拦截器中增加判断逻辑,根据返回数据的特有字段匹配对应的判别器值再注入。
- 注入前可以先判断字段是否已存在,避免覆盖接口返回的同名字段。
内容的提问来源于stack exchange,提问作者astur
相关产品推荐
相关产品推荐

