Онлайн-компилятор TypeScript _extends терпит неудачу (фактически не расширяется) - PullRequest
0 голосов
/ 24 июня 2018

Попробуйте эту ссылку , которая включает следующий класс 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 голосов
/ 25 июня 2018

Я нашел рабочее решение , основанное на другом решении SO thread .Хитрость заключается в добавлении этой строки:

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()
0 голосов
/ 24 июня 2018

Для начала, я чувствую, что вы нашли ошибку - пожалуйста, сообщите о ней в сообщениях о машинописи. (см. Комментарий jcalz).

Что касается причин, есть техническое объяснение.

Функция Array является "особенной" по-разному, и один из них заключается в том, что функция ведет себя одинаково независимо от того, вызываете ли вы ее напрямую или как конструктор ( ссылка ):

Когда Array вызывается как функция, а не как конструктор, он также создает и инициализирует новый объект Array. Таким образом, вызов функции Array (…) эквивалентен выражению создания объекта new Array (…) с теми же аргументами.

Поскольку TypeScript предполагает, что _super.apply(this, arguments) вернет this, но вместо этого возвращается новый экземпляр, ваша переменная a фактически содержит чистый Array экземпляр, а не ExtArray.

Кстати, то особое поведение, которое я упомянул о Array, также верно и для других нативных объектов, например, RegExp.


Что касается самого Array(...), он предназначен для правильной обработки вызова super(...), но, поскольку он вызывается косвенно через apply, он не получает правильный new.target, и это не работает.

Потенциальным решением этой проблемы может быть вызов super(arguments) или отображение его с помощью Reflect.construct(this, arguments).

...