TypeScript在线编译器_extends失败(实际上没有扩展)

时间:2018-06-24 15:44:43

标签: typescript class prototype

尝试this link,其中包括以下TS类,该类扩展了另一个类:

class ExtArray<T> extends Array<T> { 
    log() { 
        console.log(this)
    }
}

var a = new ExtArray(1,2,3)
a.log()

a.log应该确实存在,而且TS能够对其进行编译。但是,JS输出无法调用ExtArray.prototype.log:

VM107:22 Uncaught TypeError: a.log is not a function
    at <anonymous>:22:3

输出:

var __extends = (this && this.__extends) || (function () {
    var 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 function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var ExtArray = /** @class */ (function (_super) {
    __extends(ExtArray, _super);
    function ExtArray() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    ExtArray.prototype.log = function () {
        console.log(this);
    };
    return ExtArray;
}(Array));
var a = new ExtArray(1, 2, 3);
a.log();

怎么了?

2 个答案:

答案 0 :(得分:1)

首先,我强烈认为您已找到一个错误-请向打字稿问题报告该错误。(请参阅jcalz的评论)。

关于造成这种情况的原因,有技术上的解释。

Array函数在各种方式上都是“特殊的”,其中之一是,无论您直接调用它还是作为构造函数(link),该函数的行为都相同:

  

Array 作为函数而不是构造函数调用时,它还会创建并初始化一个新的Array对象。因此,函数调用 Array(...)等效于具有相同参数的对象创建表达式 new Array(...)

由于TypeScript假设_super.apply(this, arguments)将返回this,但是返回一个新实例,所以您的a变量实际上包含一个纯Array实例,而不是一个{{ 1}}。

顺便说一句,我提到的关于ExtArray的特殊行为也适用于其他本机对象,例如Array


对于RegExp本身,它是为了正确处理Array(...)的调用,但是由于它是通过super(...)间接调用的,因此不会收到正确的{{1} },这是行不通的。

编译器对此的潜在解决方案可能是调用apply或将其反映为new.target

答案 1 :(得分:0)

我基于working solution找到了another SO thread solution。诀窍是添加以下行:

Object.setPrototypeOf(this, ExtArray.prototype);

到构造函数。一切看起来像这样:

class ExtArray<T> extends Array<T> { 
    constructor(...args) { 
        super(...args)
        Object.setPrototypeOf(this, ExtArray.prototype);
    }
    log() { 
        console.log(this)
    }
}

var a = new ExtArray(1,2,3)
a.log()