我正在使用async
函数调用一个现有的基于承诺的API,该API拒绝了带有类型化错误的承诺。
你可以这样嘲笑这种行为:
interface ApiError {
code: number;
error: string;
}
function api(): Promise<any> {
return new Promise((resolve, reject) => {
reject({ code: 123, error: "Error!" });
});
}
现在有了promises,我可以将错误类型注解为ApiError
:
api().catch((error: ApiError) => console.log(error.code, error.message))
但是当使用async
时,如果我尝试在try ... catch()
中注解错误类型:
async function test() {
try {
return await api();
} catch (error: ApiError) {
console.log("error", error);
}
}
编译时出错:
Catch子句变量不能有类型注解。
那么,我怎么知道我期待的是什么样的错误呢?我需要在catch()
块中写一个Assert吗?这是async的一个bug/不完整的特性吗?
5条答案
按热度按时间ruarlubt1#
在TypeScript中,
catch
子句变量可能没有类型注解(除了TypeScript 4.0中的unknown
)。这并不特定于async
。以下是Anders Hejlsberg的解释:我们不允许在catch子句上使用类型注解,因为我们无法知道异常的类型。您可以抛出任何类型的对象,并且系统生成的异常(如内存不足异常)在技术上随时都可能发生。
您可以检查catch主体中是否存在
error.code
和error.message
属性(选择性地使用使用者定义的型别保护)。ax6ht2ek2#
您不能直接将自定义类型分配给错误,但可以使用type guard。type guard是一个函数,它帮助TypeScript的编译器确定错误的类型。
编写一个带有类型 predicate 的类型保护是非常简单的。你只需要实现一个布尔检查,它接受一个值,并判断这个值是否具有你的自定义类型的属性。
对于您的示例,我可以看到您的
ApiError
有一个名为code
的自定义属性,因此类型保护可能如下所示:注意
x is ApiError
返回类型,这是一个类型 predicate !使用上面的
isApiError
函数,TypeScript将有可能检测到您的自定义错误类型:您可以在此处看到类型保护的作用:https://www.youtube.com/watch?v=0GLYiJUBz6k
mccptt673#
此错误与
async
无关。您不能键入catch变量。原因很简单:TypeScript中的类型只存在于代码编译之前,一旦编译完成,您得到的就是无类型的JavaScript。
在catch子句上使用类型过滤器需要在运行时检查错误的类型,而且没有可靠的方法来完成这一任务,所以我认为这样的特性不太可能得到支持。
oalqel3c4#
简单的解决方案
您只需要使用类型Assert来转换错误类型。
eoxn13cs5#
另一个选项是验证错误示例,见下图: