77

如何将方法添加到基本类型,比如数组?在全局模块中,这将被识别

interface Array {
   remove(o): Array;
}

但是把实际的实现放在哪里呢?

4

7 回答 7

124

您可以使用原型来扩展 Array:

interface Array<T> {
    remove(o: T): Array<T>;
}

Array.prototype.remove = function (o) {
    // code to remove "o"
    return this;
}

如果您在一个模块中,您需要明确指出您指的是全局Array<T>,而不是在您的模块中创建本地Array<T>接口:

declare global {
    interface Array<T> {
        remove(o: T): Array<T>;
    }
}
于 2012-10-09T15:11:43.360 回答
62

declare global似乎是 TypeScript 2.1 的门票。注意它Array.prototype是 type any[],所以如果你想让你的函数实现检查一致性,最好自己添加一个泛型类型参数。

declare global {
  interface Array<T> {
    remove(elem: T): Array<T>;
  }
}

if (!Array.prototype.remove) {
  Array.prototype.remove = function<T>(this: T[], elem: T): T[] {
    return this.filter(e => e !== elem);
  }
}
于 2017-01-01T04:47:57.030 回答
13

添加到 Rikki Gibson 的回答中,

export{}
declare global {
    interface Array<T> {
        remove(elem: T): Array<T>;
    }
}

if (!Array.prototype.remove) {
  Array.prototype.remove = function<T>(elem: T): T[] {
      return this.filter(e => e !== elem);
  }
}

如果没有 export{} TS 错误“全局范围的增强只能直接嵌套在外部模块或环境模块声明中。”

于 2018-03-28T11:48:18.920 回答
6

从 TypeScript 1.6 开始,您可以“本地”扩展任意表达式,例如内置类型。

TypeScript 的新功能

TypeScript 1.6 增加了对扩展计算构造函数的任意表达式的类的支持。这意味着现在可以在类声明中扩展内置类型。

类的扩展子句以前需要指定类型引用。它现在接受一个表达式,可选地后跟一个类型参数列表。表达式的类型必须是具有至少一个构造签名的构造函数类型,该构造签名的类型参数数量与 extends 子句中指定的类型参数的数量相同。匹配构造签名的返回类型是类实例类型继承的基类型。实际上,这允许在扩展子句中指定真正的类和“类类”表达式。

// Extend built-in types

class MyArray extends Array<number> { }
class MyError extends Error { }

// Extend computed base class

class ThingA {
    getGreeting() { return "Hello from A"; }
}

class ThingB {
    getGreeting() { return "Hello from B"; }
}

interface Greeter {
    getGreeting(): string;
}

interface GreeterConstructor {
    new (): Greeter;
}

function getGreeterBase(): GreeterConstructor {
    return Math.random() >= 0.5 ? ThingA : ThingB;
}

class Test extends getGreeterBase() {
    sayHello() {
        console.log(this.getGreeting());
    }
}
于 2015-10-19T15:03:05.957 回答
3

扩展Array

这是一个扩展Array和添加remove方法的示例。这是一个 JavaScript 示例

/** @template T */
class List extends Array {
  /**
   * Remove an item from the list and return the removed item
   * @param {T} item
   * @return {T}
   */
  remove(item) {
    const index = this.indexOf(item);
    if (index === -1) {
      throw new Error(`${item} not in list`);
    }
    this.splice(index, 1);
    return item;
  }
}

const arr = new List(1, 2, 3);
console.log(arr.remove(3)); // 3
console.log(arr); // [1, 2]

这是一个 TypeScript 示例。

我添加了一个构造函数并将它的参数推送到数组中。(无法做到super(...items)

class List<T> extends Array {
  constructor(...items: T[]) {
    super();
    this.push(...items);
  }

  public remove(item: T): T {
    const index = this.indexOf(item);
    if (index === -1) {
      throw new Error(`${item} not in list`);
    }
    this.splice(index, 1);
    return item;
  }
}
于 2021-07-29T13:28:12.273 回答
3
class MyArray<T> extends Array<T> {
    remove: (elem: T) => Array<T> = function(elem: T) {
        return this.filter(e => e !== elem);
    }
}
let myArr = new MyArray<string>();
myArr.remove("some");

这适用于我的打字稿 v2.2.1!

于 2017-03-27T15:14:21.143 回答
-1

我只需要做同样的事情并创建一个包含映射的通用函数。

getDistinctValuesFromArray<T,R>(array: T[], mapping: (values: T) => R): R[] {
    return Array.from([...new Set(array.map(mapping))]);
}

你可以这样称呼它: getDistinctValuesFromArray<ArrayType, ElementType>(yourArray, a => a.elem) 为了具体化,我喜欢添加特定类型,如 ArrayType 和 ElementType。那些你需要用你的类型确定替换的。

于 2020-03-30T19:24:50.077 回答