I tried to throw a custom error and print my "CustomError" class name in the console instead of "Error", but with no success:
class CustomError extends Error { constructor(message: string) { super(`Lorem "${message}" ipsum dolor.`); this.name = 'CustomError'; } } throw new CustomError('foo');
The output is Uncaught Error: Load "foo" very pain
.
What I expected: Uncaught CustomError: Lorem "foo" ipsum dolor
.
I was wondering if it could be done using just TS (without messing with JS prototypes)?
The problem is that when you call
super
and the new object does not have the expected prototype chain, i.e. it is an instance ofError
, not an instance ofCustomError
.This problem can be solved elegantly using 'new.target', which is supported since Typescript 2.2, see here: https://www.typescriptlang.org/docs/handbook/release-notes/ typescript-2-2.html
The advantage of using
new.target
is that you don't have to hardcode the prototype, like some of the other answers asked here. This has the further advantage that classes inheriting fromCustomError
will also automatically get the correct prototype chain.If you were to hardcode the prototype (e.g.
Object.setPrototype(this, CustomError.prototype)
),CustomError
itself would have a working prototype chain, but any class fromCustomError
inheritance will be broken, e.g. instances ofclass VeryCustomError will not be the expected
instanceof VeryCustomError
, but justinstanceof CustomError
.See also: https://github.com/Microsoft/TypeScript/issues /13965#issuecomment-278570200
Are you using typescript version 2.1 and converting to ES5? Check this section of the breaking changes page for possible issues and workarounds: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built -ins-like -error-array-and-map-may-no-longer-work
Relevant bits: