为自定义打字稿错误实例实施 instanceof 检查?

Posted

技术标签:

【中文标题】为自定义打字稿错误实例实施 instanceof 检查?【英文标题】:Implementing instanceof checks for custom typescript Error instances? 【发布时间】:2019-07-30 15:14:52 【问题描述】:

Typescript 有这个instanceof checks on custom errors 问题,但不清楚我们需要做什么才能让instanceof 正常工作。例如对于这个异常,我们如何让instanceof 工作:

    /**
     * @param message The error message
     * @param value The value that violates the constraint
     * @param field The name of the field
     * @param type The expected type for the field
     * @param constraint The name of the constraint violated
     * @param code The application or module code for the error
     */
    export class IsError extends Error 
      constructor(
        public message:string,
        public value: any, 
        public field?:string, 
        public type?: string,
        public constraint?: string,
        public code?:string) 
          super(message);
          this.name = 'IsError';
          Object.setPrototypeOf(this, IsError.prototype);      
      
    

This link says we can manually adjust the prototype,这是我正在做的,但是这个测试没有通过:

it("should be an instance of IsError", () => 
   let error = new IsError("This is an IsError", 'value');
   expect(error instanceof IsError)).toBeTruthy();
);

更正

我在测试...IsError)) 中有一个额外的括号,我误认为测试没有通过。我更新了测试,现在它可以工作了。所以这个问题中的例子IsError实现是正确的。

IIUC 这个实现在 ES5 中不起作用,但是包含 CoreJS 的 AFAIK 客户端可以。

【问题讨论】:

不扩展 Error 类而只依赖 Object.setPrototypeOf 行会发生什么? 试过了 - 检查测试仍然没有通过...... 我创建了一个对我有用的基本示例 (here)。我使用 Typescript 3.0.1。 Duh ... 感谢您指出这一点 - 我在开玩笑的测试中多了一个括号,看起来好像测试没有通过。现在一切都好。例子更简单。请把它作为答案发布,我会检查它。 【参考方案1】:

阅读https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work

现在,@Mathyn 和 @TmTron 的完整实现答案:

/**
 * Base Error.
 */
class BaseError extends Error 
  constructor(message?: string) 
    const trueProto = new.target.prototype;
    super(message);
    Object.setPrototypeOf(this, trueProto);
  


class Err1 extends BaseError 
const e1 = new Err1();
console.log(e1 instanceof Err1); // true
console.log(e1 instanceof Error); // true

class Err2 extends Err1 
const e2 = new Err2();
console.log(e2 instanceof Err1); // true
console.log(e2 instanceof Err2); // true
console.log(e2 instanceof Error); // true

class NoBaseErr extends Error 
const x = new NoBaseErr();
console.log(x instanceof Error); // true
console.log(x instanceof NoBaseErr); // false !!!

import BaseError from 'ts-base-error';

见:https://www.npmjs.com/package/ts-base-error

【讨论】:

【参考方案2】:

AFAIK,Object.setPrototypeOf() 需要 es6 - ref

TypeScript#13965 中的这段代码对我有用(在 es5 中)

export class MyError extends Error 
    __proto__: Error;
    constructor(message?: string) 
        const trueProto = new.target.prototype;
        super(message);

        // Alternatively use Object.setPrototypeOf if you have an ES6 environment.
        this.__proto__ = trueProto;
    

【讨论】:

【参考方案3】:

您的代码中出现的问题(正如您正确指出的那样)是您的断言中多了一个括号。

为了完整起见,一个有效且最小的示例如下所示:

class CustomError extends Error 
    constructor() 
        super();

        Object.setPrototypeOf(this, CustomError.prototype);
    


let error = new CustomError();

console.log(error instanceof CustomError); // Will log 'true'

【讨论】:

如果你尝试扩展CustomError,你需要对constructor()做同样的事情。 在这种情况下,constructor() 没有扩展基本实现,例如:尝试做new CustomError('Test').message...

以上是关于为自定义打字稿错误实例实施 instanceof 检查?的主要内容,如果未能解决你的问题,请参考以下文章

特定 javascript 实例化模式的正确打字稿定义是啥

打字稿`可以用不同的约束子类型实例化`错误

带有箭头功能的打字稿装饰器

typescript CRC16 ITU打字稿实施

打字稿错误未使用 useState 钩子定义

如何使用打字稿读取 json 数据? [复制]