代码之家  ›  专栏  ›  技术社区  ›  Rostys

函数上“Can throw exception”标记的传播[重复]

  •  0
  • Rostys  · 技术社区  · 3 年前

    在Java中,我会声明这样一个函数:

    public boolean Test(boolean test) throws Exception {
      if (test == true)
        return false;
      throw new Exception();
    }
    

    我可以在不处理异常的情况下使用此函数。

    如果可能的话,如何在Typescript中进行同样的操作?编译器会告诉我,如果没有try/catch,我就无法使用该函数。

    0 回复  |  直到 7 年前
        1
  •  179
  •   Estus Flask    7 年前

    TypeScript中没有这样的功能。只有当函数返回错误而不是抛出错误时,才可以指定错误类型(这种情况很少发生,而且很容易成为反模式)。

    唯一相关的类型是 never 。只有当函数肯定抛出错误时,它才适用,它不能比这更具体。它和其他类型一样,只要不引起类型问题,就不会引起类型错误:

    function Test(): never => {
      throw new Error();
    }
    
    Test(); // won't cause type error
    let test: boolean = Test(); // will cause type error
    

    当函数有返回值的可能性时, 从不 由返回类型吸收。

    可以在函数签名中指定,但仅供参考:

    function Test(test: boolean): boolean | never {
      if (test === true)
        return false;
    
      throw new Error();
    }
    

    它可以向开发人员提供一个提示,即可能会出现未处理的错误(以防函数体不清楚),但这不会影响类型检查,也不能强制 try..catch ; 考虑该函数的类型 (test: boolean) => boolean 通过打字系统。

        2
  •  38
  •   Klesun Gian Marco    5 年前

    您可以用标记函数 @throws 至少是jsdoc。即使它在typescript编译器中不提供静态分析错误,一些好的IDE或linter仍然可能 report a warning 如果你试图忽略抛出的函数。。。

    /** 
     * @throws {Error}
     */
    function someFunc() {
        if (Math.random() < 0.5) throw Error();
    }
    someFunc();
    

    enter image description here

        3
  •  25
  •   backus sompnd    6 年前

    现在不可能。您可以查看此请求的功能: https://github.com/microsoft/TypeScript/issues/13219

        4
  •  3
  •   Toby Hobson    3 年前

    来自函数背景,我更喜欢在返回类型中指定预期的错误(也称为检查异常)。Typescript联合和类型保护使其变得简单:

    class ValidationError {
      constructor(readonly message: string) {}
    
      static isInstance(err: unknown): err is ValidationError {
        if (err === undefined) return false
        if (typeof err !== 'object') return false
        if (err === null) return false
        return err instanceof ValidationError
      }
    }
    
    function toInt(num: string): number | ValidationError {
      const result = Number.parseInt(num)
      if (result === undefined) return new ValidationError(`Invalid integer ${num}`)
      return result
    }
    
    // caller
    const result = toInt("a")
    if (ValidationError.isInstance(result))
      console.log(result.message)
    else
      console.log(`Success ${result}`)
    

    这样,函数签名会向其他开发人员突出潜在的错误。更重要的是IDE&transpiler将强制开发人员处理它们(在大多数情况下)。例如,这将失败:

    const result = toInt("a")
    const doubled = result * 2
    
    error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type
    
        5
  •  2
  •   lmiguelmh    5 年前

    您可以处理JavaScript的 Error 作为Java的 RuntimeException (未检查的异常)。 您可以扩展JavaScript的 错误 但是 you have to use Object.setPrototypeOf 恢复原型链,因为 错误 破坏了它。对setPrototypeOf的需求在中进行了解释 this answer

    export class AppError extends Error {
        code: string;
    
        constructor(message?: string, code?: string) {
            super(message);  // 'Error' breaks prototype chain here
            Object.setPrototypeOf(this, new.target.prototype);  // restore prototype chain
            this.name = 'AppError';
            this.code = code;
        }
    }
    
    
        6
  •  2
  •   snnsnn    3 年前

    如其他答案所示,在typescript中,易出错操作的返回类型为 never 。无法将函数标记为throws,但是可以使用实用程序类型使其更易于识别:

    type Result<OK = any> = OK | never;
    

    或者你可以让它更加引人注目:

    type Result<OK = any, Error = never> = OK | Error;
    

    同样,这些只是针对眼睛的,没有办法强制执行try/catch块。

    如果您想强制处理错误,请使用promise。林特人可以兑现未经处理的承诺。“typescript esint”具有“无浮动promise”规则。

    https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-floating-promises.md

    此外,当存在未处理的promise时,一些运行时会发出错误。

        7
  •  1
  •   Flavien Volken    6 年前

    你不能使用纯ts(v<3.9),我希望它将来可以使用。 然而,一种变通方法是可能的,它包括在方法的签名中隐藏可能抛出的类型,然后在catch块中恢复这些类型。 我在这里用这个变通方法制作了一个包: https://www.npmjs.com/package/ts-throwable/v/latest

    用法大致如下:

    import { throwable, getTypedError } from 'ts-throwable';
    class CustomError extends Error { /*...*/ }
    
    function brokenMethod(): number & throwable<CustomError> {
        if (Math.random() < 0.5) { return 42 };
        throw new CustomError("Boom!");
    }
    
    try {
        const answer: number = brokenMethod()
    }
    catch(error){
        // `typedError` is now an alias of `error` and typed as `CustomError` 
        const typedError = getTypedError(error, brokenMethod);
    }
    
    
        8
  •  1
  •   Nico    4 年前

    关于这个话题,这似乎是一个有趣的公关 https://github.com/microsoft/TypeScript/pull/40468

    本PR介绍:

    • 一个新的类型级表达式:throw-type_expr。当前投掷类型 仅在实例化时抛出。
    • 一种新的内在类型 TypeToString打印类型
        9
  •  0
  •   P Varga    5 年前

    不是TypeScript,而是 Hegel 可能感兴趣的是,哪一个是JavaScript的另一个类型检查器,并且具有此功能。你会写道:

    function Test(test: boolean): boolean | $Throws<Exception> {
      if (test)
        return false;
      throw new Exception();
    }
    

    看见 https://hegel.js.org/docs/magic-types#throwserrortype

        10
  •  0
  •   Daniel Wasserlauf    2 年前

    这是不可能的,而且可能不会持续很长一段时间。 https://github.com/microsoft/TypeScript/issues/13219#issuecomment-1515037604 https://github.com/microsoft/TypeScript/issues/13219#issuecomment-1806338593 在一般的github讨论之前有一个链接,但github的讨论线程很长,而且是封闭的,所以我想省去人们阅读讨论的工作量,只需将两个最相关的评论链接起来。

    我不能对链接到这个帖子的相关答案发表评论,否则我会的。

    对于更高的TLDR: -TS团队不想在规范化类型化错误方面迈出第一步,因为它还没有出现在社区中,JS中也不存在任何类型的错误处理(如Java)。