2

Why this code returns false?

class MyException extends Error {
    constructor(message: string) {
        super(message);
    }
}

const e = new MyException('blah');
console.log(e instanceof MyException); // returns 'false'

It does not happen when I execute the following code:

class Base {
    constructor(message: string) {
        console.log(message);
    }
}

class MyClass extends Base {
    constructor(message: string) {
        super(message);
    }
}

const e = new MyClass('blah');
console.log(e instanceof MyClass); // returns 'true'
Cequiel
  • 3,505
  • 6
  • 27
  • 44
  • Possible duplicate of [Typescript - Extending Error class](https://stackoverflow.com/questions/41102060/typescript-extending-error-class) – nemesv Dec 22 '17 at 12:17

1 Answers1

2

It is a known issue : instanceof is broken when class extends Error type related to to the Polymer standard support with TypeScript feature.

Proposed workarounds are :

  • creating an intermediary class
  • setting the prototype

Unfortunately this is a change that we made to try to try to adopt a more standard-compliant emit so that we could enable Polymer to work with TypeScript.

For background, was an intentional change in 2.2 (see #12123 and the section on our wiki), but is difficult to overcome through compilation. I believe there's some conversation in #12790 for workarounds.

A workaround you can take now is create an intermediate class that you can extend from.

export interface MyErrorStatic {
    new (message?: string): RxError;
}
export interface MyError extends Error {}

export const MyError: MyErrorStatic = function MyError(this: Error, message: string) {
    const err = Error.call(this, message);
    this.message = message;
    this.stack = err.stack;
    return err;
} as any;

export class HttpError extends MyError {
    // ...
}

In TypeScript 2.2, you'll be able to set the prototype on your own.

// Use this class to correct the prototype chain.
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;
    }
}
davidxxx
  • 125,838
  • 23
  • 214
  • 215