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

时间:2017-03-06 05:22:44

标签: 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!" });
  });
}

现在有了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()块中写一个断言吗?这是异步的错误/不完整功能吗?

3 个答案:

答案 0 :(得分:13)

在TypeScript中,catch子句变量可能没有类型注释。这不是async特有的。这是an explanation from Anders Hejlsberg

  

我们不允许在catch子句上使用类型注释,因为实际上无法知道异常将具有什么类型。您可以抛出任何类型的对象,并且系统生成的异常(例如内存不足异常)可以在任何时候在技术上发生。

您可以检查catch主体中是否存在error.codeerror.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