TypeScript 如何定义 API 返回类型

在前端开发里,我们经常要跟后端的API接口打交道——比如用户点击登录,前端发个请求过去,后端返回的是带token的对象,还是带错误信息的对象?要是前后端对不上,比如后端返回了个“token”,前端却按“userID”用,就会出现各种bug,改起来还特别麻烦。这时候TypeScript就能帮上大忙,其中定义API返回类型就是最实用的功能之一。

先搞懂:为什么要给API返回值定类型?

举个生活化的例子:你点外卖,商家给的餐是“米饭+炒菜”,你肯定知道怎么吃;但要是商家给了个“陌生盒子”,你就得拆了才知道能不能吃。API返回值就像这个“外卖盒子”——如果是纯JS,它就是个“没贴标签的盒子”,你得自己拆内容、记格式,还容易记错;而TypeScript给返回值定类型,就相当于给盒子贴了标签,你拿到手就知道里面有什么,用的时候不会乱。

TypeScript 如何定义 API 返回类型

比如前端写了个获取用户信息的请求:如果没定类型,你写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返回的结构,不用再猜来猜去。

上一篇 JavaScript undefined 和 null 区别