instanceof using ES6 class Inheritance chain doesn't work

Focusing on the last piece of your example

You're converting this code using BabelJS to make it compatible

class BTError extends Error {}
class SomeError extends BTError {}
class SpecificError extends SomeError {}

console.log('6.', new SpecificError() instanceof Error);
console.log('7.', new SpecificError() instanceof BTError);
console.log('8.', new SpecificError() instanceof SomeError);

This is the transpiled version of the code above

'use strict';

function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
    }
}

function _possibleConstructorReturn(self, call) {
    if (!self) {
        throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }
    return call && (typeof call === "object" || typeof call === "function") ? call : self;
}

function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
            value: subClass,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });
    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

var BTError = function(_Error) {
    _inherits(BTError, _Error);

    function BTError() {
        _classCallCheck(this, BTError);

        return _possibleConstructorReturn(this, (BTError.__proto__ || Object.getPrototypeOf(BTError)).apply(this, arguments));
    }

    return BTError;
}(Error);

var SomeError = function(_BTError) {
    _inherits(SomeError, _BTError);

    function SomeError() {
        _classCallCheck(this, SomeError);

        return _possibleConstructorReturn(this, (SomeError.__proto__ || Object.getPrototypeOf(SomeError)).apply(this, arguments));
    }

    return SomeError;
}(BTError);

var SpecificError = function(_SomeError) {
    _inherits(SpecificError, _SomeError);

    function SpecificError() {
        _classCallCheck(this, SpecificError);

        return _possibleConstructorReturn(this, (SpecificError.__proto__ || Object.getPrototypeOf(SpecificError)).apply(this, arguments));
    }

    return SpecificError;
}(SomeError);

console.log('6.', new SpecificError() instanceof Error); // 6. true
console.log('7.', new SpecificError() instanceof BTError); // 7. false
console.log('8.', new SpecificError() instanceof SomeError); // 8. false

I think the problem stems from the _inherit method, that assigns to subClass.prototype not the superClass.prototype directly, but an object created by merging that and another set of default properties.

With this chain of prototypes the inheritance would work but the instanceof operator would fail to travel it by reference, and so you get false where you expect true.

Apparently, according to this bug report, it's a known and expected behaviour (ie. limitation) and a possible workaround is to use babel-plugin-transform-builtin-extend


Had this problem with TypeScript. Solved it by adding the following in the class constructor after the super calls:

Object.setPrototypeOf(this, YOUR_CLASS_HERE.prototype);

Not sure if it helps you.