在TypeScript中,异步函数(async/await)始终返回Promise。返回值的类型这样指定:Promise<Type>。在描述函数时,显式地给结果类型添加注解非常重要,这样TypeScript才能正确地处理Promise内的类型。如果中间值与声明的值不一致,则可能会出现类型化错误。
异步函数:
async function fetchUser(id: number): Promise<User> { const response = await fetch(`/api/user/${id}`); const data: User = await response.json(); return data; }
如果函数需要返回错误或拒绝,则Promise的类型不应直接描述错误(Promise<Error>),因为Promise的拒绝不被类型化,而是通过catch捕获。
Promise链的类型化很重要:
function getNumber(): Promise<number> { return Promise.resolve(42); } getNumber().then(val => val.toFixed(2)); // TypeScript知道val是一个数字
问题: 异步函数可以返回除了Promise以外的东西吗?
答案: 不可以。异步函数始终返回一个Promise对象。如果显式返回非Promise,TypeScript会自动将返回值包装在Promise中。
async function test() { return 1; } const result = test(); type ResultType = typeof result; // Promise<number>
故事
一位开发者编写了一个函数,没有明确类型化返回值,假设它返回特定类型的对象。随着逻辑的改变,函数开始返回其他类型,但这没有立即被注意到,因为TypeScript基于类型推断没有报错。最终错误只在运行时表现出来,当函数的消费者尝试访问不存在的属性时。
故事
在一个项目中,Promise链没有被类型化。试图访问结果中不存在的方法导致了错误。因此,结果then(response => response.data)被视为any,字段或方法的错误捕获仅在运行时显现。该错误进入了生产环境,仅通过用户反馈才被发现。
故事
异步函数被声明为Promise<Error>类型,认为这可以捕获错误,但实际上错误并没有通过throw抛出,Promise以不同类型的值被拒绝。这导致了错误和有效值的隐式混合,以及在处理Promise结果逻辑中的漏洞。