如何将方法添加到基本类型,比如数组?在全局模块中,这将被识别
interface Array {
remove(o): Array;
}
但是把实际的实现放在哪里呢?
您可以使用原型来扩展 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>;
}
}
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);
}
}
添加到 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 错误“全局范围的增强只能直接嵌套在外部模块或环境模块声明中。”
从 TypeScript 1.6 开始,您可以“本地”扩展任意表达式,例如内置类型。
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());
}
}
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;
}
}
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!
我只需要做同样的事情并创建一个包含映射的通用函数。
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。那些你需要用你的类型确定替换的。