有一些问题(除了普遍的看法是you should not extend native object prototypes)。首先是当你声明一个泛型接口或类型时,它的类型参数必须是一个裸名,而不是某个其他类型的函数。所以你不能拥有
interface Foo<T, U[]> {} // error
如果你要求第二个类型参数是一个数组,你应该使用generic constraint:
interface Foo<T, U extends any[]> {} // okay
下一个问题是,如果您以任何方式更改类型参数或其约束,您将无法merge declarations 泛型类型。 Map<K, V> 已在 the standard library 中定义,因此您无法将其更改为 Map<TKey, TValue[]> 或 Map<TKey, TValue extends any[]> 甚至 Map<K, V extends any[]>。您只需将其保留为 Map<K, V>。
您添加的新方法需要 V 是一个数组类型才能有意义。而且你不能在你的声明中限制V。你卡住了吗?不!幸运的是,您可以使用称为 this parameter 的 TypeScript 功能。这个想法是,您可以在函数或方法的参数列表的开头添加一个名为 this 的参数。当您调用该方法时,您不使用 this 参数,但 TypeScript 将强制您仅在其 this 上下文匹配的对象上调用该方法。
像这样:
// no error
declare global {
interface Map<K, V> {
SetInArray<V>(this: Map<K, V[]>, key: K, value: V): boolean;
}
}
Map.prototype.SetInArray = function <K, V>(this: Map<K, V[]>, key: K, value: V): boolean {
let isNew: boolean = false;
if (this.has(key) == false) {
this.set(key, []);
isNew = true;
}
let items: V[] = this.get(key)!;
items.push(value);
return isNew;
};
让我们试试吧:
const numberArrayMap = new Map<string, number[]>();
numberArrayMap.set("a", [1, 2, 3])
numberArrayMap.SetInArray("a", 4); // okay
const numberMap = new Map<string, number>();
numberMap.set("a", 4)
numberMap.SetInArray("a", 4); // error
// The 'this' context of type 'Map<string, number>' is not assignable
// to method's 'this' of type 'Map<string, number[]>'.
// Type 'number' is not assignable to type 'number[]'.
这正是你想要的行为,我想。请注意numberArrayMap 如何让您调用SetInArray(),但numberMap 不能,并且错误告诉您即使Map 确实有SetInArray 方法,由于this 不兼容,您根本无法调用它上下文。
好的,希望对您有所帮助。祝你好运!