Creating elegant custom exceptions is easy with ecmascript classes.

In most languages we subclass the base Exception class to create our own exceptions. But since javascript did not have classes until ES5, creating custom exceptions was cumbersome. So much that people usually just throw the standard Error object with the desired custom message string.

But now that ES6 has classes, we can just extend Error:

class BufferFullError extends Error {}

And there we have our own custom Error! Except it does not work.

expect(()=>buffer.read()).toThrow(BufferEmptyException);
    Expected the function to throw an error of type:
      "BufferEmptyException"
    Instead, it threw:
      Error

The reason is babel-6 (a common transpiler used to convert modern ES6 code to ES5 so that it runs in most browsers) does not support subclassing of built-in classes.

But there is a plugin we can use to achieve this: babel-plugin-transform-builtin-extend.

Install it via npm or yarn and add this to babel config:

"plugins": [
  ["babel-plugin-transform-builtin-extend", {
    "globals": ["Error", "Array"]
  }]
]

Protip: It is a good practice to add a custom error message:

export class BufferFullException extends Error {
  constructor(message) {
    super();
    this.message = message || 'Buffer is full.';
  }
}

References:

1 . More info on why babel does not support it: https://stackoverflow.com/questions/33870684/why-doesnt-instanceof-work-on-instances-of-error-subclasses-under-babel-node/33877501#33877501

2 . I learnt it because of a problem I was solving with exercism: https://github.com/exercism/xecmascript/issues/280