谈谈在Tyepscript(version:2.2.2)扩展(extends)built-in类型(e.g. Array)的问题

前两天用typescript写代码的时候,像扩展一下内置的数据类型:Array,结果发现编译出的js文件,运行时提示找不到扩展的方法。google以后发现如下说法:

Why doesn't extending built-ins like Error, Array, and Map work?

In ES2015, constructors which return an object implicitly substitute the value of this for any callers of super(...).It is necessary for generated constructor code to capture any potential return value of super(...) and replace it with this.

As a result, subclassing Error, Array, and others may no longer work as expected.This is due to the fact that constructor functions for Error, Array, and the like use ECMAScript 6's new.target to adjust the prototype chain;however, there is no way to ensure a value for new.target when invoking a constructor in ECMAScript 5.Other downlevel compilers generally have the same limitation by default.

下面给大家 一个实例和详细的解释,分享一下心得。

问题起因:

在TypeScript中,extends built-in type, 并且使用ES5库(target:ES5)进行编译。


实例:

TS代码:

class NewArray<T> extends Array<T>{
getFirst() {
return 'NewArray';
}
}
var newAry = new NewArray<string>();
console.log(newAry.getFirst()); // here will error out of undefined method

编译后的JS代码:

var NewArray = (function (_super) {
__extends(NewArray, _super);
function NewArray() {
// this will return the Array instead of this(NewArray) which means "this" is substituted
return _super !== null && _super.apply(this, arguments) || this;
}
NewArray.prototype.getFirst = function () {
return 'NewArray';
};
return NewArray;
}(Array));

大家可以留意一下, built-in的数据类型,在调用apply方法时,会返回自身的数据类型,导致子类(NewArray)的构造函数返回的是Array,而不是NewArray,以至于在实例化NewArray时,它的__proto__是Array的prototype而不是NewArray的prototype,所以导致NewArray的实例,并没有包涵NewArray prototype里定义的方法(i.e. getFirst)。

但是在自定义类的扩展没有问题,大家可以调试看看,因为自动的类,最终可以保证构造函数返回的this,没有被降级。


解决方法:

目前没有找到太好的解决方案,只能等TypeScript下一个版本可以解决这个问题。目前在使用ES5库的时候,先不要extends built-in的类型了。如果大家找到什么好的方法,请回复我哦。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章