【问题标题】:Unable to write Extension Method for Map<TKey, TValue[]> in TypeScript无法在 TypeScript 中为 Map<TKey, TValue[]> 编写扩展方法
【发布时间】:2019-05-01 23:23:06
【问题描述】:

我是 Angular/TS 的新用户,喜欢使用扩展方法。他们在标准类型上工作得很好,但现在我正在尝试为 Map 编写一个,其中 V 将是数组,但不幸的是它似乎不起作用。

我正在尝试做的是扩展方法将映射 V 初始化为数组并推送值或推送(如果已经初始化)。

declare global {
interface Map<TKey, TValue[]>
 {
    SetInArray(key:TKey, value:TValue):boolean;
 }
}


Map.prototype.SetInArray = function<TKey, TValue>(key:TKey, value:TValue):boolean {

let isNew:boolean = false;

if(this.has(key) == false){

    this.set(key, []);

    isNew = true;

}

let items:TValue[] = this.get(key);

items.push(value);

return isNew;
};


export {};

请指教

谢谢

【问题讨论】:

标签: angular typescript generics


【解决方案1】:

有一些问题(除了普遍的看法是you should not extend native object prototypes)。首先是当你声明一个泛型接口或类型时,它的类型参数必须是一个裸名,而不是某个其他类型的函数。所以你不能拥有

interface Foo<T, U[]> {} // error

如果你要求第二个类型参数是一个数组,你应该使用generic constraint:

interface Foo<T, U extends any[]> {} // okay

下一个问题是,如果您以任何方式更改类型参数或其约束,您将无法merge declarations 泛型类型。 Map&lt;K, V&gt; 已在 the standard library 中定义,因此您无法将其更改为 Map&lt;TKey, TValue[]&gt;Map&lt;TKey, TValue extends any[]&gt; 甚至 Map&lt;K, V extends any[]&gt;。您只需将其保留为 Map&lt;K, V&gt;

您添加的新方法需要 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 不兼容,您根本无法调用它上下文。

好的,希望对您有所帮助。祝你好运!

【讨论】:

  • 它就像一个魅力和解释帮助我更详细地学习泛型。非常感谢:)
猜你喜欢
  • 2014-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-25
  • 1970-01-01
  • 2011-06-15
  • 2016-06-14
  • 2011-01-16
相关资源
最近更新 更多