TypeScript async await 类型怎么写
做前端开发的朋友,肯定都遇过写异步代码的坑:用JavaScript写回调地狱还好,换成TypeScript想给async函数加类型,反而容易卡壳——要么不知道怎么定返回值,要么一写就报错。其实核心问题是没搞懂「异步函数的类型是怎么套的」,跟着生活化的例子走,分分钟就能搞明白。
先搞懂基础:async函数的返回值不是普通值
很多人刚学TypeScript时,会直接给async函数加function fetchData(): Promise<string>,但真遇到异步返回对象或数组时,就会乱改类型。其实不用复杂术语,换个场景理解:你点外卖,商家的「异步出餐」就像async函数,你拿到的「外卖盒」(返回值)不是直接的饭菜本身,而是装饭菜的「盒子」——这个盒子就是Promise,盒子里的东西才是你真正要的数据。

举个最常见的例子:写一个接口请求用户昵称的异步函数,返回的是字符串。新手可能会写成:
`typescript
// 错误写法:把盒子当成了饭菜,直接写返回值类型
async function getUserName(): string {
const res = await fetch('/api/user/name')
return res.json()
}
`
运行会直接报错:因为await拿到的是Promise<string>里的内容,而函数声明说要返回string,实际返回了Promise<string>,类型对不上。正确的做法是把「盒子类型」写上,也就是:
`typescript
// 正确写法:用Promise包裹真实数据类型
async function getUserName(): Promise<string> {
const res = await fetch('/api/user/name')
return res.json() // 自动推断出await后是string,套上Promise就是返回类型
}
`
这里的Promise<string>就是盒子的类型,string是盒子里的饭菜,完全对应。
遇到复杂类型?给盒子里的内容定「说明书」
如果异步返回的不是字符串,而是带多个字段的对象(比如用户信息),直接用object太模糊,用interface或type给它定个「说明书」就清晰了。比如要获取用户的年龄和昵称,先写个类型说明:
`typescript
// 给用户信息定说明书,就像外卖的餐品清单
type UserInfo = {
name: string
age: number
}
`
然后把async函数的返回值改成「装着这个说明书的盒子」:
`typescript
// 函数返回值是Promise<UserInfo>,对应「盒子里是符合UserInfo的对象」
async function getUserInfo(userId: number): Promise<UserInfo> {
const res = await fetch(/api/user/${userId})
return res.json() // 自动匹配UserInfo类型,不会少字段
}
`
如果要返回数组(比如用户的收藏列表),逻辑一样:数组的类型是UserInfo[],所以盒子类型就是Promise<UserInfo[]>。比如:
`typescript
async function getUserFavorites(userId: number): Promise<UserInfo[]> {
const res = await fetch(/api/user/${userId}/favorites)
return res.json()
}
`
这就像外卖的「多人套餐盒」,盒子里装的是一堆符合「UserInfo」规则的餐品,类型完全对应。
进阶场景:函数参数也可以加类型
除了返回值,异步函数的参数类型也容易忘加——就像你点外卖要报手机号(参数),没说清楚商家没法对应订单。比如之前的getUserInfo需要传userId,就可以给参数加类型:
`typescript
// 参数userId是number,就像报的是数字格式的手机号
async function getUserInfo(userId: number): Promise<UserInfo> {
const res = await fetch(/api/user/${userId})
return res.json()
}
`
如果参数是复杂对象(比如要传查询条件),同样可以用interface定义:
`typescript
type UserQuery = {
keyword: string
limit?: number // 可选参数,像外卖的「备注可选」
}
async function searchUsers(query: UserQuery): Promise<UserInfo[]> {
const res = await fetch(/api/user/search?keyword=${query.keyword}&limit=${query.limit ?? 10})
return res.json()
}
`
这里的limit?: number就是可选参数,不用每次都传,TypeScript会自动识别。
最后再总结一下,TypeScript里async/await的类型写法核心就两点:一是异步函数的返回值永远要套Promise,里面写真实数据的类型;二是复杂数据提前用type或interface定义清楚,就不会出错。不用记晦涩的术语,把Promise当成装数据的盒子,一切就清晰了。