我知道我可以创建一个基本的数组扩展,就像这样,它适用于所有数组,无论该数组中的类型是什么。
export {};
declare global {
interface Array<T> {
isEmpty(): boolean;
}
}
// determines if an array is empty, or if the contents of the items in the array are empty
Array.prototype.isEmpty = function() {
if (this.length == 0) {
return true;
} else {
return this.some((c) => c != null && c != '');
}
};
但是我想为仅包含特定对象的数组创建扩展?我已经尝试过,但出现错误
import { MyObject } from './my-object';
export {};
declare global {
interface Array<MyObject> {
isEmpty(): boolean;
}
}
// determines if an array is empty, or if the contents of the items in the array are empty
Array.prototype.isEmpty = function() {
if (this.length == 0) {
return true;
} else {
return this.some((c) => c != null && c != '');
}
};
我试图通过查看 here 来找出答案但我似乎无法找出正确的语法。
非常感谢任何帮助:)
最佳答案
你想做什么?正如 @NitzanTomer 指出的,你不能像 TypeScript 中那样专门化泛型,其中 Array<MyObject>
有一个方法isEmpty()
,但是Array<string>
才不是。根据您计划如何使用它,有些事情可以让您接近。
选项 1:扩展 Array
根据您的要求制作原型(prototype)(不推荐)
我能得到的最接近您具体要求的就是要求 the this
parameter的isEmpty()
类型为Array<MyObject>
:
declare global {
interface Array<T> {
isEmpty(this: Array<MyObject>): boolean;
}
}
// note the error below
Array.prototype.isEmpty = function() {
if (this.length == 0) {
return true;
} else {
return this.some((c) => c != null &&
c != '' // error! c has to be MyObject, not string
);
}
};
(顺便说一句,当您将数组元素(现在需要为 isEmpty()
)与 MyObject
值进行比较时, string
的实现会出现错误。好消息是 TypeScript 正在提醒您这一点这样你就可以修复它。)
您现在可以继续调用 isEmpty()
在 MyObject
的数组上:
declare let myObject1: MyObject;
declare let myObject2: MyObject;
const arrayOfMyObject: MyObject[] = [myObject1, myObject2];
arrayOfMyObject.isEmpty(); // okay
现在,isEmpty()
方法存在在所有数组上,但是尝试在不同类型的数组上调用它会给出错误:
const arrayOfStrings: string[] = ['a', 'b'];
arrayOfStrings.isEmpty(); // error, string is not MyObject
所以这可能适合你。
话虽如此,扩展原生原型(prototype)如 Array
是 almost always considered a bad idea .
选项 2:扩展所选 Array
具有新方法的实例
更好的想法是使用额外的方法创建一个全新的类,或者采用单独的 Array
实例并向其中添加方法,而不会污染 Array
原型(prototype)。这是实现后者的一种方法:
interface MyObjectArray<T extends MyObject> extends Array<T>{
isEmpty(): boolean;
}
const isEmpty = function(this: Array<MyObject>) {
if (this.length == 0) {
return true;
} else {
return this.some((c) => c != null &&
c != '' // error! c is MyObject, not string
);
}
};
function toMyObjectArray<T extends MyObject>(arr: Array<T>): MyObjectArray<T> {
const ret = arr as MyObjectArray<T>;
ret.isEmpty = isEmpty.bind(ret);
return ret;
}
现在我们有一个名为 MyObjectArray
的新界面其中包括额外的方法。如果您有 MyObject[]
的现有实例,您可以将其转换为MyObjectArray
使用toMyObjectArray()
函数,它添加 isEmpty()
的方法。然后你可以像这样使用它:
declare let myObject1: MyObject;
declare let myObject2: MyObject;
const arrayOfMyObject = [myObject1, myObject2];
arrayOfMyObject.isEmpty(); // error, no such method
const myObjectArray = toMyObjectArray(arrayOfMyObject); // convert
myObjectArray.isEmpty(); // okay
// can't convert an array of anything else
const arrayOfStrings = toMyObjectArray(['a', 'b', 'c']);
每次需要使用 isEmpty()
时,都会有一个额外的步骤,即调用转换函数。 ,这可能会让您不太满意。
选项 3:使用独立版 isEmpty()
函数,而不是方法
事实上,如果你不打算搞乱 Array.prototype
,并且您必须在数组实例上调用函数,您不妨跳过额外的接口(interface)并使用独立的 isEmpty()
而不是为方法烦恼:
const isMyObjectArrayEmpty = function(arr: Array<MyObject>) {
if (arr.length == 0) {
return true;
} else {
return arr.some((c) => c != null &&
c != '' // error! c is MyObject, not string
);
}
};
declare let myObject1: MyObject;
declare let myObject2: MyObject;
const arrayOfMyObject = [myObject1, myObject2];
isMyObjectArrayEmpty(arrayOfMyObject); // okay
const arrayOfStrings = ['a', 'b', 'c'];
isMyObjectArrayEmpty(arrayOfStrings); // error
<小时/>
这些是我所看到的选项。
关于javascript - 为特定类类型的数组创建 typescript 扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46216986/