The extends keyword is used in class declarations or class expressions to create a class that is a child of another class.
Based on Karel Bílek's answer, I'd make a small change to the constructor
:
class ExtendableError extends Error {
constructor(message) {
super(message);
this.name = this.constructor.name;
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
} else {
this.stack = (new Error(message)).stack;
}
}
}
// now I can extend
class MyError extends ExtendableError {}
var myerror = new MyError("ll");
console.log(myerror.message);
console.log(myerror instanceof Error);
console.log(myerror.name);
console.log(myerror.stack);
This will print MyError
in the stack, and not the generic Error
.
It will also add the error message to the stack trace - which was missing from Karel's example.
It will also use captureStackTrace
if it's available.
With Babel 6, you need transform-builtin-extend (npm) for this to work.
Combining this answer, this answer and this code, I have made this small "helper" class, that seems to work fine.
class ExtendableError extends Error {
constructor(message) {
super();
this.message = message;
this.stack = (new Error()).stack;
this.name = this.constructor.name;
}
}
// now I can extend
class MyError extends ExtendableError {
constructor(m) {
super(m);
}
}
var myerror = new MyError("ll");
console.log(myerror.message);
console.log(myerror instanceof Error);
console.log(myerror.name);
console.log(myerror.stack);
Try in REPL
To finally put this to rest. In Babel 6 it is explicit that the developers do not support extending from built in. Although this trick will not help with things like Map
, Set
, etc. it does work for Error
. This is important as one of the core ideas of a language that can throw an exception is to allow custom Errors. This is doubly important as Promises become more useful since they to are designed to reject an Error.
The sad truth is you still need to perform this the old way in ES2015.
Example in Babel REPL
class MyError {
constructor(message) {
this.name = 'MyError';
this.message = message;
this.stack = new Error().stack; // Optional
}
}
MyError.prototype = Object.create(Error.prototype);
On the other hand there is a plugin for Babel 6 to allow this.
https://www.npmjs.com/package/babel-plugin-transform-builtin-extend
Update: (as of 2016-09-29) After some testing it appears that babel.io does not properly account for all the asserts (extending from a custom extended Error). But in Ember.JS extending Error works as expected: https://ember-twiddle.com/d88555a6f408174df0a4c8e0fd6b27ce
Edit: Breaking changes in Typescript 2.1
Extending built-ins like Error, Array, and Map may no longer work.
As a recommendation, you can manually adjust the prototype immediately after any super(...) calls.
Editing Lee Benson original answer a little bit works for me. This also adds stack
and additional methods of ExtendableError
class to the instance.
class ExtendableError extends Error {
constructor(message) {
super(message);
Object.setPrototypeOf(this, ExtendableError.prototype);
this.name = this.constructor.name;
}
dump() {
return { message: this.message, stack: this.stack }
}
}
class MyError extends ExtendableError {
constructor(message) {
super(message);
Object.setPrototypeOf(this, MyError.prototype);
}
}
var myerror = new MyError("ll");
console.log(myerror.message);
console.log(myerror.dump());
console.log(myerror instanceof Error);
console.log(myerror.name);
console.log(myerror.stack);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With