你如何在async catch()中使用类型错误

Aar*_*all 15 typescript

我正在使用一个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.codeerror.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

  • 请注意,您可能应该使用“unknown”而不是“any”,因为“any”会抑制类型错误...“unknown”强制您正确断言 1) 错误是一个对象 2) 它不为 null 3) `x.code` 是一个数字 (3认同)

JLR*_*she 5

此错误与无关async。您不能键入catch变量。

原因很简单:TypeScript中的类型仅在编译代码之前存在。编译后,您所拥有的就是无类型的JavaScript。

在catch子句上使用类型过滤器将需要在运行时检查错误的类型,并且根本没有可靠的方法可以做到这一点,所以我想说这种功能永远不可能得到支持。


Mas*_*iri 5

一个简单的解决方案

您只需要使用类型断言来转换错误类型。

catch (err) {
  const error = err as CustomErrorType;
  ...
}
Run Code Online (Sandbox Code Playgroud)