为什么 TypeScript 中的 instanceof 不适用于继承 class?

Why is instanceof in TypeScript not working for inherited class?

我有以下 class:

class ApiError extends Error {
    httpCode: number
    constructor(message:string, httpCode:number = 400) {
        super(message);
        this.httpCode = httpCode;
    }
}

export class ErrorForbidden extends ApiError {
    constructor(message:string = 'Forbidden') {
        super(message, 403);
    }
}

然后我像这样创建一个实例:

const error = new ErrorForbidden();
console.info(error instanceof ErrorForbidden); // false
console.info(error instanceof Error); // true

所以它似乎检测到它是 Error 的实例而不是 ErrorForbidden 的实例,尽管我就是这样创建它的。

知道为什么它不起作用吗?以及如何让它发挥作用?

如果您将 TypeScript 设置为编译为 ES5 或其他 ES2015 之前版本的 JavaScript,TypeScript 无法正确子类化 Error,因为在 ES2015 之前不可能这样做.因此,它会产生 Error 但不是 ErrorForbidden 的东西(在你的情况下)。

为您的代码生成的 JavaScript(如果我省略 export 以便在 Playground 中使用)看起来像这样,如果它设置为 ES5 输出:

"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var ApiError = /** @class */ (function (_super) {
    __extends(ApiError, _super);
    function ApiError(message, httpCode) {
        if (httpCode === void 0) { httpCode = 400; }
        var _this = _super.call(this, message) || this;
        _this.httpCode = httpCode;
        return _this;
    }
    return ApiError;
}(Error));
var ErrorForbidden = /** @class */ (function (_super) {
    __extends(ErrorForbidden, _super);
    function ErrorForbidden(message) {
        if (message === void 0) { message = 'Forbidden'; }
        return _super.call(this, message, 403) || this;
    }
    return ErrorForbidden;
}(ApiError));
var error = new ErrorForbidden();
console.info(error instanceof ErrorForbidden); // false
console.info(error instanceof Error); // true

...显示 false, true.

Live on the Playground

设置为ES2015输出时与此比较:

"use strict";
class ApiError extends Error {
    constructor(message, httpCode = 400) {
        super(message);
        this.httpCode = httpCode;
    }
}
class ErrorForbidden extends ApiError {
    constructor(message = 'Forbidden') {
        super(message, 403);
    }
}
const error = new ErrorForbidden();
console.info(error instanceof ErrorForbidden); // false
console.info(error instanceof Error); // true

...显示 true, true.

Live on the Playground