【问题标题】:How do you use typed errors in async catch()你如何在异步 catch() 中使用类型错误
【发布时间】:2017-03-06 05:22:44
【问题描述】:

我正在使用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!" });
  });
}

现在有了promise,我可以将错误类型注释为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() 块中写一个断言吗?这是异步的错误/不完整功能吗?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    在 TypeScript 中,catch 子句变量可能没有类型注释(as of TypeScript 4.0unknown 除外)。这不是特定于async。这里是an explanation from Anders Hejlsberg

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

    您可以检查 catch 正文中是否存在 error.codeerror.message 属性(可以选择使用 user-defined type guard)。

    【讨论】:

    • 谢谢。我想这与Promise.catch() 没有类型参数的原因相同。不过,我希望我能写下我预期的错误......很多 TS 只是写你所期望的,当然不能保证你的任何类型在运行时都是正确的!
    • 如果您没有可用的错误类型,这可以转换为 catch (e) { if ((e as {code: string}).code === 'YOUR ERROR CODE') { ... } 并且在 Benny Neugebauer 的回答中建议了更简洁的实现
    【解决方案2】:

    您不能直接为错误分配自定义类型,但可以使用 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

    【讨论】:

    • 请注意,您可能应该使用unknown 而不是any,因为any 抑制类型错误...unknown 强制您正确断言 1) 错误是一个对象 2 ) 它不为空 3) x.code 是一个数字
    【解决方案3】:

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

    原因很简单:TypeScript 中的类型只存在于代码编译完成之前。一旦编译完成,您所拥有的就是无类型 JavaScript。

    在 catch 子句上使用类型过滤器需要在运行时检查错误的类型,而且根本没有可靠的方法来做到这一点,所以我会说不太可能支持这样的功能。

    【讨论】:

      【解决方案4】:

      一个简单的解决方案

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

      catch (err) {
        const error = err as CustomErrorType;
        ...
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-18
        • 1970-01-01
        • 1970-01-01
        • 2021-06-20
        • 2018-07-12
        • 1970-01-01
        • 1970-01-01
        • 2019-07-04
        相关资源
        最近更新 更多