为特定类类型

时间:2017-09-14 10:44:38

标签: javascript typescript web typescript2.0

我知道我可以创建一个基本的数组扩展,就像这样,无论该数组中的类型是什么,它都适用于所有数组。

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找出答案,但我似乎无法弄清楚正确的语法。

任何帮助非常感谢:)

2 个答案:

答案 0 :(得分:2)

你想做什么?正如@NitzanTomer所指出的那样,你不能像TypeScript中那样专门化泛型,其中Array<MyObject>有方法isEmpty(),但Array<string>却没有。根据您打算如何使用它,有些事情可以让您接近。

选项1:根据您的要求扩展Array原型(不推荐)

我最接近你明确要求的是要求this的{​​{1}}参数属于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的实现会出错。好消息是TypeScript会提醒您这一点,以便您可以修复它。)

现在,您可以继续在string

的数组上调用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 等原生原型是almost always considered a bad idea

选项2:使用新方法

扩展选定的Array个实例

更好的想法是使用额外方法创建一个全新的类,或者采用单个Array实例并将方法添加到它们而不会污染Array原型。这是一种做后者的方法:

Array

现在我们有一个名为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']); 时,还有一个额外的步骤就是调用转换函数,这可能会让您不太喜欢。

选项3:使用独立的isEmpty()功能,而不是方法

事实上,如果您不打算使用isEmpty(),并且必须在数组实例上调用函数,那么您也可以跳过额外的接口并使用独立的Array.prototype而不是打扰方法:

isEmpty()

所以这些是我看到的选项。希望有所帮助;祝你好运!

答案 1 :(得分:0)

使用此方法无法为特定类型扩展数组。 Typescript使用泛型类型擦除,因此在运行时无法区分$("body:visible").child().each(function(i){ //Here you can play with the elements as you want. }); Array<A>。 您可以创建一个派生数组类型,添加所需的方法,示例代码here,但您必须新建该类,而不是使用Array<B>创建简单数组