Extending Error in Javascript with ES6 syntax & Babel
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 extendclass 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 extendclass 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);
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.
Custom Error pattern
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