javascript - 为特定类类型的数组创建 typescript 扩展

标签 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 来找出答案但我似乎无法找出正确的语法。

非常感谢任何帮助:)

最佳答案

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

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

我能得到的最接近您具体要求的就是要求 the this parameterisEmpty()类型为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)如 Arrayalmost 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/

相关文章:

javascript - 语法错误: Token '{' Invalid Key - Errors even when displaying correctly

javascript - 如何在模糊事件之后获取焦点事件?

reactjs - 属性...在类型 'IntrinsicAttributes & ...' 上不存在

javascript - 在 Angular 2 App 中转换双向绑定(bind)属性中的日期

正则表达式 - 选择查询字符串值的值并在第一个&符号处停止

没有密码的Azure webapp ssl证书pfx

javascript - 单击鼠标后,在进入下一页之前在 div 内运行脚本

angular - 依赖注入(inject)抽象类 typescript (Angular2)

html - 是否有 SSL 握手的 dns 预取等价物?

javascript - 如何在不返回 Angular 数据的 http.post 请求上使用 'toPromise()'?