Есть несколько проблем (кроме того факта, что не следует расширять прототипы нативных объектов ).Во-первых, когда вы объявляете универсальный интерфейс или тип, его параметр типа должен быть пустым именем, а не функцией какого-либо другого типа.Таким образом, у вас не может быть
interface Foo<T, U[]> {} // error
Если вам требуется, чтобы параметр второго типа был массивом, вы должны использовать универсальное ограничение :
interface Foo<T, U extends any[]> {} // okay
Следующая проблема заключается в том, что вы не можете объединить объявления универсальных типов, если вы каким-либо образом измените параметры типа или их ограничения.Map<K, V>
уже определен в стандартной библиотеке , поэтому вы не можете изменить его на Map<TKey, TValue[]>
или Map<TKey, TValue extends any[]>
или даже Map<K, V extends any[]>
.Вы должны просто оставить его как Map<K, V>
.
Новый метод, который вы добавляете, требует, чтобы V
был типом массива, чтобы иметь смысл.И вы не можете ограничить V
в своем объявлении.Вы застряли?Нет!К счастью, вы можете использовать функцию TypeScript под названием this
параметр .Идея состоит в том, что вы можете добавить параметр с именем 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
context.
Хорошо, надеюсь, это поможет.Удачи!