【问题标题】:Why Catch clause variable type annotation must be any?为什么 Catch 子句变量类型注解必须是 any?
【发布时间】:2022-05-20 00:47:02
【问题描述】:

我正在使用 yup 验证表单,但在尝试使这个 catch 起作用时遇到了这种类型错误:

Catch 子句变量类型注解必须为 any 或 unknown if 指定 1196

我的代码:

const handleSubmit = async (): Promise<void> => {
    try {
      const isValid = await userSchema.validate(values, { abortEarly: false });
      console.log(isValid);
    } catch (err: ValidationError) {
      console.log(err);
      const errors = getValidationErrors(err);
    }

getValidationErrors 函数:

export function getValidationErrors(err: yup.ValidationError): Errors {
  console.error(err);
  const validationErrors: Errors = {};
  err.inner.forEach((error) => {
    if (error.path) validationErrors[error.path] = error.message;
  });
  return validationErrors;
}

在搜索它时,我发现 Typescript 不接受子句捕获参数的类型......这是为什么呢?这在 Java 或其他语言中很常见...我的意思是...我的解决方案是属性 err: any... 但是 type any 不就是永远不会使用的东西吗?

【问题讨论】:

  • TS 在运行时不存在,因此为catch 声明它是没有意义的。使用unknown 而不是any
  • 我明白了……这很有意义。谢谢大佬!

标签: typescript


【解决方案1】:

Typescript 不允许您这样做,因为 typescript 无法在编译时验证代码唯一可以抛出的东西是 ValidationError。就此而言,您也不知道:如果您收到 RangeError,因为已超出最大调用堆栈,该怎么办?显然这不太可能(在调用它之前你必须建立一个大的调用堆栈),但是这段代码并不能保证它不会发生。

这在 Java 或其他语言中很常见......

不同的语言对其设计有不同的限制。例如,在 Java 中,您可以定义函数将抛出哪些错误作为函数定义的一部分,如

public static FileInputStream example(String fileName) throws FileNotFoundException {

javascript 和 typescript 都没有办法在函数定义中指定它。

java 允许你有多个 catch 块,不同类型的错误由不同的块处理,但由于 typescript 只存在于编译时,这不是一个选项。一切都必须在一个 catch 块中处理,并且必须使用显式代码来区分您正在处理的错误类型。

【讨论】:

    【解决方案2】:

    正如其他人所指出的,TS 不允许您在 catch 子句中使用“任何”或“未知”以外的类型。

    但是,您可以将错误变量转换为特定类型。使用 myVariable。

    try {
      // where some ValidationError object could be thrown
    } catch (err: unknown) {
       const errors = getValidationErrors(<ValidationError>err);
    }
    

    【讨论】:

    • 你也可以这样做const error = err as Error | AxiosError
    • @TaiyrBegeyev 在我使用“as Type”的经验中是绝对的最后手段,但它是一种反模式。这个答案是处理这种情况的正确方法。错误未知
    【解决方案3】:

    您不能在 Typescript 中为 catch 子句变量编写特定注释,因为在 Javascript 中,catch 子句将捕获抛出的任何异常,而不仅仅是指定类型的异常。

    Java 允许您(实际上,需要您)编写异常的类型,因为在编译时它能够检查(针对已检查的异常类型)是否可以抛出该异常,但更重要的是,在运行时它会检查抛出的异常类型,如果异常类型与catch 子句匹配,则仅捕获它(执行catch 块)。

    在Typescript中,如果你只想捕获特定类型的异常,你必须捕获抛出的任何东西,检查它是否是你要处理的异常类型,如果不是,再次抛出它:

    try {
        // code that could throw ValidationError
    } catch(e: unknown) {
        if(!(e instanceof ValidationError)) { throw e; }
        // code to handle ValidationError
    }
    

    在这种情况下,if 语句之后,e 的类型将缩小为ValidationError,您可以访问e.message

    【讨论】:

      【解决方案4】:

      根据 Typescript 文档的this piece,在 TS 4.0 版本之前,catch 子句变量的类型通常为any,在处理第一个时可能会导致新的错误。

      例子:

      try {
        // Do something
      } catch (x) {
        console.log(x.message);
      }
      

      如果 x 中没有 message 属性怎么办? 是的,现在您遇到了一个新错误

      unknown 类型作为any 的安全替代品存在,因为unknown 类型的操作是非法的,因此您必须在执行任何操作之前对unknown 变量进行类型检查。

      同样根据文档,任何类型:

      缺乏任何可能在无效操作上出错的类型安全。

      因此我们可以得出结论,您应该继续避免使用any

      希望我的回答对你有帮助。

      【讨论】:

        【解决方案5】:

        您不能在 typescript 中为 catch 子句变量编写特定的注释,这是因为在 javascript 中,catch 子句将捕获抛出的任何异常,而不仅仅是指定类型的异常。

        在打字稿中,如果你只想捕捉特定类型的异常,你必须捕捉抛出的任何东西,检查它是否是你想要处理的异常类型,如果不是,再次抛出它。

        含义:在做任何事情之前,先检查抛出的错误是否是axios错误。

        try {
        // do something
        }catch (err) {
             // check if error is an axios error
             if (axios.isAxiosError(err)) {
                        
              // console.log(err.response?.data)
              if (!err?.response) {
                  console.log("No Server Response");
               } else if (err.response?.status === 400) {
                 console.log("Missing Username or Password");
               } else if (err.response?.status === 401) {
                 console.log("Unauthorized");
                } else {
                console.log("Login Failed");
              } 
           } 
        }
        

        【讨论】:

          猜你喜欢
          • 2017-08-17
          • 2020-09-11
          • 2021-11-08
          • 2019-11-15
          • 1970-01-01
          • 2019-08-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多