Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing instanceof checks for custom typescript Error instances?

Typescript has this instanceof checks on custom errors issue, but it's not clear what we need to do to get instanceof working. For example for this exception how would we get instanceof working:

    /**
     * @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, which is what I'm doing, but this test is not passing:

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

Correction

I had an additional parenthesis in the test ...IsError)) that I mistook for the test not passing. I updated the test and now it work. So the example IsError implementation in this question is correct.

IIUC this implementation will not not work in ES5, but AFAIK clients that include CoreJS will be ok.

like image 544
Ole Avatar asked Mar 08 '19 14:03

Ole


2 Answers

What goes wrong in your code (as you correctly pointed out) was an extra parenthesis in your assertion.

Just to be complete, a working and minimal example would look like this:

class CustomError extends Error {
    constructor() {
        super();

        Object.setPrototypeOf(this, CustomError.prototype);
    }
}

let error = new CustomError();

console.log(error instanceof CustomError); // Will log 'true'
like image 101
Mathyn Avatar answered Nov 14 '22 20:11

Mathyn


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

Now, a complete implementation of @Mathyn and @TmTron answers:

/**
 * 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 !!!

Package

import BaseError from 'ts-base-error';

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

like image 11
Eduardo Cuomo Avatar answered Nov 14 '22 21:11

Eduardo Cuomo