我正在使用一个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!" });
});
}
Run Code Online (Sandbox Code Playgroud)
现在有了promises,我可以将错误类型注释为ApiError:
api().catch((error: ApiError) => console.log(error.code, error.message))
Run Code Online (Sandbox Code Playgroud)
但是在使用时,async如果我尝试在以下位置注释错误类型try ... catch():
async function test() {
try {
return await api();
} catch (error: ApiError) {
console.log("error", error);
}
}
Run Code Online (Sandbox Code Playgroud)
它编译错误:
Catch子句变量不能有类型注释.
那么,我怎么知道我期待的是什么样的错误?我需要在catch()块中写一个断言吗?这是异步的错误/不完整功能吗?
Ste*_*ett 19
在TypeScript中,catch子句变量可能没有类型注释.这不是特定的async.以下是Anders Hejlsberg的解释:
我们不允许在catch子句上使用类型注释,因为实际上无法知道异常将具有什么类型.您可以抛出任何类型的对象,并且系统生成的异常(例如内存不足异常)可以在任何时候在技术上发生.
您可以在catch主体中检查是否存在error.code和error.message属性(可选地使用用户定义的类型保护).
Ben*_*uer 18
您不能直接为错误分配自定义类型,但可以使用类型保护。类型保护是一个帮助 TypeScript 编译器找出错误类型的函数。
编写带有类型谓词的类型保护非常容易。您只需要实现一个布尔检查,它接受一个值并确定该值是否具有您的自定义类型的属性。
根据您的示例,我可以看到您ApiError有一个名为 的自定义属性code,因此类型保护可能如下所示:
function isApiError(x: unknown): x is ApiError {
if (x && typeof x === 'object' && 'code' in x) {
return true;
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
请注意x is ApiError返回类型。这是一个类型谓词!
使用isApiError上面的函数,TypeScript 可以检测您的自定义错误类型:
interface ApiError {
code: number;
error: string;
}
function isApiError(x: unknown): x is ApiError {
if (x && typeof x === 'object' && 'code' in x) {
return true;
}
return false;
}
try {
return await api();
} catch (error) {
if (isApiError(error)) {
// Thanks to the type guard, TypeScript knows know what "error" is
console.log(error.code);
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在此处查看正在运行的类型保护:https://www.youtube.com/watch ?v=0GLYiJUBz6k
此错误与无关async。您不能键入catch变量。
原因很简单:TypeScript中的类型仅在编译代码之前存在。编译后,您所拥有的就是无类型的JavaScript。
在catch子句上使用类型过滤器将需要在运行时检查错误的类型,并且根本没有可靠的方法可以做到这一点,所以我想说这种功能永远不可能得到支持。
您只需要使用类型断言来转换错误类型。
catch (err) {
const error = err as CustomErrorType;
...
}
Run Code Online (Sandbox Code Playgroud)