TypeScript 如何定义 API 返回类型
在前端开发里,我们经常要跟后端的API接口打交道——比如用户点击登录,前端发个请求过去,后端返回的是带token的对象,还是带错误信息的对象?要是前后端对不上,比如后端返回了个“token”,前端却按“userID”用,就会出现各种bug,改起来还特别麻烦。这时候TypeScript就能帮上大忙,其中定义API返回类型就是最实用的功能之一。
先搞懂:为什么要给API返回值定类型?
举个生活化的例子:你点外卖,商家给的餐是“米饭+炒菜”,你肯定知道怎么吃;但要是商家给了个“陌生盒子”,你就得拆了才知道能不能吃。API返回值就像这个“外卖盒子”——如果是纯JS,它就是个“没贴标签的盒子”,你得自己拆内容、记格式,还容易记错;而TypeScript给返回值定类型,就相当于给盒子贴了标签,你拿到手就知道里面有什么,用的时候不会乱。

比如前端写了个获取用户信息的请求:如果没定类型,你写res.data.name的时候,可能自己都忘了后端有没有“name”这个字段,要是后端哪天改了字段名,代码就直接报错了。但用TypeScript定了类型,写错了编辑器会直接标红,连测试都不用跑就能发现问题。
怎么定义API返回类型?用“接口”就够了
TypeScript里定义对象类型最常用的是“接口(interface)”,刚好适合用来描述API返回的对象结构。这里用真实开发里最常见的场景举例:比如调用后端的“登录接口”,返回的是“登录成功后的用户信息+token”,我们可以这么做:
先写一个接口,描述返回值的结构:
`typescript
// 定义登录接口的返回类型
interface LoginResponse {
// 用户名,必填项
username: string;
// 用户ID,必填项,数字类型
userId: number;
// 登录凭证,必填项,字符串类型
token: string;
// 可选字段:如果是会员的话有,普通用户没有,加个“?”表示可选
isVip?: boolean;
}
`
这里的“?”很实用,比如会员字段不是所有人都有,就不用强制写,避免类型报错。
再用这个类型去接收API返回值:
`typescript
// 模拟调用登录接口,返回值类型用刚才定义的LoginResponse
async function login() {
// 假设后端返回的是{ username: "小明", userId: 123, token: "abc123" }
const res = await fetch("/api/login", { method: "POST" });
const data: LoginResponse = await res.json(); // 给返回值加类型注解
// 这时候用data.username就不会报错,编辑器也能自动补全字段
console.log(data.username); // 输出“小明”
}
`
要是你写错了,比如把data.token写成data.auth,编辑器会直接提示“类型LoginResponse上没有auth属性”,从根源上避免写错。
处理不同的返回情况:用“联合类型”兼容
有时候API可能返回两种结果:要么是成功带数据,要么是失败带错误信息,这时候用“联合类型”就能轻松应对。比如登录失败时,后端会返回{ error: "密码错误" },我们可以把两种情况的类型合起来:
`typescript
// 定义“登录接口可能的两种返回类型”
type LoginResult = LoginResponse | { error: string };
async function loginWithCheck() {
const res = await fetch("/api/login");
const data: LoginResult = await res.json();
// 用类型缩小判断当前是哪种情况
if ("error" in data) {
console.log("登录失败:", data.error); // 处理错误
} else {
console.log("登录成功,token是:", data.token); // 处理成功
}
}
`
这样不管后端返回哪种格式,TypeScript都能帮你识别,不用自己写一堆判断逻辑,还不容易出错。
小技巧:复用类型,减少重复
如果多个API返回的字段有重叠,比如“获取用户信息”和“修改用户信息”都返回username和userId,可以用“继承接口”的方式复用,不用重新写一遍:
`typescript
// 基础用户信息接口
interface BaseUser {
username: string;
userId: number;
}
// 登录返回的用户信息,继承基础接口,再加token
interface LoginResponse extends BaseUser {
token: string;
}
// 获取用户信息的返回,继承基础接口,再加昵称
interface UserInfoResponse extends BaseUser {
nickname: string;
}
`
这样改基础字段的时候,只需要改BaseUser就行,不用到处找地方改,省时间还不容易漏。
说白了,TypeScript定义API返回类型,就是把“凭感觉用数据”变成“按规则用数据”,既能减少bug,又能让代码更清晰——哪怕是刚学前端的人看你的代码,也能一眼看懂API返回的结构,不用再猜来猜去。