6

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

如果指定了 Catch 子句变量类型注释,则必须为 any 或 unknown 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……但是键入 any 不就是永远不会使用的东西吗?

4

4 回答 4

7

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

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

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

public static FileInputStream example(String fileName) throws FileNotFoundException {

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

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

于 2021-09-01T22:28:26.327 回答
6

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

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

try {
  // where some ValidationError object could be thrown
} catch (err: unknown) {
   const errors = getValidationErrors(<ValidationError>err);
}
于 2021-09-15T17:18:43.640 回答
2

您不能catch在 Typescript 中为子句变量编写特定的注释,因为在 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

于 2021-09-01T22:40:10.847 回答
1

根据这篇Typescript 文档,在 TS 4.0 版本之前,catch 子句变量通常被键入为any,并且在处理第一个时可能会导致新的错误。

例子:

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

如果没有message财产x怎么办?是的,现在你有一个新的错误

unknowntype 作为 的安全替代存在any,因为使用unknowntype 的操作是非法的,所以你必须在做任何事情之前对你的unknown变量进行类型检查。

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

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

所以我们可以得出结论,你应该继续避免使用any.

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

于 2021-09-01T23:04:09.513 回答