Class 从 Typescript 1.6.2 中的内置数组扩展,在使用 [] 运算符时不会更新长度
Class extended from built-in Array in Typescript 1.6.2 does not update length while using [] operator
在我阅读 here:
时,应该可以在 ts 1.6 中扩展内置类型
TypeScript 1.6 adds support for classes extending arbitrary expression that computes a constructor function. This means that built-in types can now be extended in class declarations.
...
Some examples:
// Extend built-in types
class MyArray extends Array<number> { }
class MyError extends Error { }
...
然而,当扩展 Array 时,长度 属性 在使用 [] 运算符设置值时不会更新。推送功能工作正常,但我需要 [] 运算符。
我的例子:
class ExtendedArray<T> extends Array<T> {}
var buildinArray = new Array<string>();
var extendedArray = new ExtendedArray<string>();
buildinArray.push("A");
console.log(buildinArray.length); // 1 - OK
buildinArray[2] = "B";
console.log(buildinArray.length); // 3 - OK
extendedArray.push("A");
console.log(extendedArray.length); // 1 - OK
extendedArray[2] = "B";
console.log(extendedArray.length); // 1 - FAIL
console.dir(extendedArray); // both values, but wrong length
我是不是做错了什么?问题出在哪里?
扩展 Array
仅在 ES6 环境中受支持,因此如果您将 tsconfig.json
的 compilerSettings.target
设置为 ES3 或 ES5,这将无法正常工作。有workarounds in ES5 but I'd say it isn't worth the trouble - although you can probably use it in TypeScript since it is a superset of ES5. This book on ES6说明情况比较详细
您的代码转换为此 JavaScript 代码:
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var ExtendedArray = (function (_super) {
__extends(ExtendedArray, _super);
function ExtendedArray() {
_super.apply(this, arguments);
}
return ExtendedArray;
})(Array);
var buildinArray = new Array();
var extendedArray = new ExtendedArray();
buildinArray.push("A");
console.log(buildinArray.length); // 1 - OK
buildinArray[2] = "B";
console.log(buildinArray.length); // 3 - OK
extendedArray.push("A");
console.log(extendedArray.length); // 1 - OK
extendedArray[2] = "B";
console.log(extendedArray.length); // 1 - FAIL
console.dir(extendedArray); // both values, but wrong length
问题是括号符号没有作为 Array
原型复制的一部分进行复制:
In JavaScript, we can sub-class native data types by extending the
native prototypes. This works perfectly with the native String object;
but, when it comes to native Arrays, things don't work quite so
nicely. If we extend the Array prototype, we inherit the native array
functions; but, we no longer have the ability to use bracket notation
to set and get indexed values within the given array. Sure, we can use
push() and pop() to overcome this limitation; but, if we want to keep
the bracket notation feature functional, we have to build on top of an
existing array instance rather than truly sub-classing the Array
object.
[Source]
Axel Rauschmayer 博士有深入的 discussion and solutions here。
在我阅读 here:
时,应该可以在 ts 1.6 中扩展内置类型TypeScript 1.6 adds support for classes extending arbitrary expression that computes a constructor function. This means that built-in types can now be extended in class declarations.
...
Some examples:
// Extend built-in types class MyArray extends Array<number> { } class MyError extends Error { } ...
然而,当扩展 Array 时,长度 属性 在使用 [] 运算符设置值时不会更新。推送功能工作正常,但我需要 [] 运算符。
我的例子:
class ExtendedArray<T> extends Array<T> {}
var buildinArray = new Array<string>();
var extendedArray = new ExtendedArray<string>();
buildinArray.push("A");
console.log(buildinArray.length); // 1 - OK
buildinArray[2] = "B";
console.log(buildinArray.length); // 3 - OK
extendedArray.push("A");
console.log(extendedArray.length); // 1 - OK
extendedArray[2] = "B";
console.log(extendedArray.length); // 1 - FAIL
console.dir(extendedArray); // both values, but wrong length
我是不是做错了什么?问题出在哪里?
扩展 Array
仅在 ES6 环境中受支持,因此如果您将 tsconfig.json
的 compilerSettings.target
设置为 ES3 或 ES5,这将无法正常工作。有workarounds in ES5 but I'd say it isn't worth the trouble - although you can probably use it in TypeScript since it is a superset of ES5. This book on ES6说明情况比较详细
您的代码转换为此 JavaScript 代码:
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var ExtendedArray = (function (_super) {
__extends(ExtendedArray, _super);
function ExtendedArray() {
_super.apply(this, arguments);
}
return ExtendedArray;
})(Array);
var buildinArray = new Array();
var extendedArray = new ExtendedArray();
buildinArray.push("A");
console.log(buildinArray.length); // 1 - OK
buildinArray[2] = "B";
console.log(buildinArray.length); // 3 - OK
extendedArray.push("A");
console.log(extendedArray.length); // 1 - OK
extendedArray[2] = "B";
console.log(extendedArray.length); // 1 - FAIL
console.dir(extendedArray); // both values, but wrong length
问题是括号符号没有作为 Array
原型复制的一部分进行复制:
In JavaScript, we can sub-class native data types by extending the native prototypes. This works perfectly with the native String object; but, when it comes to native Arrays, things don't work quite so nicely. If we extend the Array prototype, we inherit the native array functions; but, we no longer have the ability to use bracket notation to set and get indexed values within the given array. Sure, we can use push() and pop() to overcome this limitation; but, if we want to keep the bracket notation feature functional, we have to build on top of an existing array instance rather than truly sub-classing the Array object.
[Source]
Axel Rauschmayer 博士有深入的 discussion and solutions here。