如何在前端根据请求成功状态为response.data添加正确TypeScript类型?
为Auth请求函数添加正确TypeScript类型标注的解决方案
问题背景
存在一个无法修改的API认证路由,返回结构如下:
- 认证成功时,返回
AuthSuccess类型:
interface AuthSuccess { token: string user: object }
- 认证失败时,错误响应返回
AuthError类型:
interface AuthError { error: string }
基于Next.js使用Axios编写的请求函数如下:
const auth = ({email, password}) => api // api是axios.create()的返回值 .post(url, {email, password}) .then((result) => ({ success: true, data: response.data // 原代码笔误:应为result.data })) .catch((error) => ({ success: false, data: error.response?.data // 此处应为AuthError类型 }))
调用时,即便校验res.success,TypeScript仍无法正确推断data的类型:
const res = await auth(data) if (res.success) { // 期望data为AuthSuccess,但TypeScript认为可能是两种类型 } else { // 期望data为AuthError,但TypeScript认为可能是两种类型 }
解决方案
使用判别式联合类型(Discriminated Union),让TypeScript能通过success字段自动缩小类型范围。
步骤1:定义完整的类型结构
首先明确请求参数类型,以及包含判别字段的结果类型:
// 请求参数类型 interface AuthProps { email: string; password: string; } // 成功结果类型(带判别式success: true) type AuthSuccessResult = { success: true; data: AuthSuccess; }; // 失败结果类型(带判别式success: false) type AuthErrorResult = { success: false; data: AuthError; }; // 联合结果类型 type AuthResult = AuthSuccessResult | AuthErrorResult;
步骤2:为Auth函数添加正确的类型标注
将函数改为async/await写法(更直观),并标注返回类型为Promise<AuthResult>,同时修正原代码笔误,对错误响应数据添加类型断言:
const auth = async ({ email, password }: AuthProps): Promise<AuthResult> => { try { const result = await api.post(url, { email, password }); return { success: true, data: result.data }; } catch (error) { // Axios无法自动推断error.response.data的类型,需手动断言 return { success: false, data: error.response?.data as AuthError }; } };
步骤3:调用时的类型推断
此时调用函数,TypeScript会自动根据success的值推断data的类型:
const res = await auth(data); if (res.success) { // res.data 自动推断为AuthSuccess类型 console.log(res.data.token); } else { // res.data 自动推断为AuthError类型 console.log(res.data.error); }
为什么之前的方案无效
- 方案1:返回
Promise<AuthSuccess | AuthError>的问题在于,这两个类型没有共同的success判别字段,TypeScript无法通过条件判断缩小类型范围。 - 方案2:条件泛型
AuthResult<T>需要在调用时明确指定泛型参数,但success的值是运行时动态决定的,无法提前确定,因此TypeScript无法正确推断类型。
内容的提问来源于stack exchange,提问作者Kyomen
相关产品推荐
相关产品推荐

