我正在使用async
函数调用现有的基于promise的API,该API拒绝带有类型错误的promise。
你可以这样模仿这种行为:
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()
块中写一个断言吗?这是异步的错误/不完整功能吗?
答案 0 :(得分:13)
在TypeScript中,catch
子句变量可能没有类型注释。这不是async
特有的。这是an explanation from Anders Hejlsberg:
我们不允许在catch子句上使用类型注释,因为实际上无法知道异常将具有什么类型。您可以抛出任何类型的对象,并且系统生成的异常(例如内存不足异常)可以在任何时候在技术上发生。
您可以检查catch主体中是否存在error.code
和error.message
属性(可选地使用user-defined type guard)。
答案 1 :(得分:2)
此错误与{{1}}无关。你不能有类型化的catch变量。
原因很简单:TypeScript中的类型仅在编译代码之前存在。一旦编译完成,你所拥有的只是无类型的JavaScript。
在catch子句上使用类型过滤器需要检查错误&#39;类型在运行时,并没有可靠的方法来做到这一点,所以我想说这样的功能不太可能得到支持。
答案 2 :(得分:0)
您不能直接为错误指定自定义类型,但可以使用 type guard。类型保护是一种帮助 TypeScript 编译器确定错误类型的函数。
使用类型谓词编写类型保护非常简单。您只需要实现一个布尔值检查,它接受 any
值并确定该值是否具有您的自定义类型的属性。
根据您的示例,我可以看到您的 ApiError
有一个名为 code
的自定义属性,因此类型保护可能如下所示:
function isApiError(x: any): x is ApiError {
return typeof x.code === 'number';
}
注意 x is ApiError
返回类型。这是一个类型谓词!
使用上面的 isApiError
函数,TypeScript 现在可以推断您的自定义错误类型:
interface ApiError {
code: number;
error: string;
}
async function test() {
const isApiError = (x: any): x is ApiError => {
return typeof x.code === 'number';
};
try {
return await api();
} catch (error) {
if (isApiError(error)) {
// Thanks to the type guard, TypeScript knows know what "error" is
console.log(error.code);
}
}
}
你可以在这里看到一个正在运行的类型保护器:https://www.youtube.com/watch?v=0GLYiJUBz6k