1

我目前正在从 JS 过渡到 TS 并且无法完全理解keyof。我找到了https://github.com/kimamula/TypeScript-definition-of-EventEmitter-with-keyof,现在我正在尝试实现这一点。一切都很顺利,直到我打开“noImplicitAny”。

我在 ts 操场上做了一个例子来展示我遇到的问题:

在构造函数中没有访问权限,K所以我必须明确地制作 Map(arg: any)才能让它工作。

创建地图时是否有避免使用任何解决方案的解决方案?

4

1 回答 1

0

问题是您试图分配 (arg: keyof T) => any(arg: T[K]) => any. keyof T表示此类中的任何属性名称T例如:

class X { test: string; test2: number; }

keyof X'test' | 'test2' 与while T[K]with相同,表示带有 nameK extends keyof T的属性的类型,因此对于上面的类,可以是或取决于传递的值TKT[K]numberstringK

因此,如果您有Emitter<X>,您基本上会尝试分配(arg: string | number) => any绝对(arg: 'test' | 'test2') => any不是类型安全的。

我的猜测是,您希望约束listener具有与类成员相同的属性类型的参数。为此,您应该使用限制Map<string, ((arg: T[keyof T]) => any) []>arg任何可能的属性类型T

class EventEmitter<T> {

  private events: Map<string, ((arg: T[keyof T]) => any) []>;

  constructor() {
    this.events = new Map<string, ((arg: T[keyof T]) => any) []>();
  }

  public getOrCreateEvents<K extends keyof T>(event: K, listener: (arg: T[K]) => any): ((arg: T[K]) => any) [] {

    return this.events.get(event) || this.events.set(event, new Array<(arg: T[K]) => any>()).get(event);
  }
}

// Test 
class X { test: string; test2: number; }
var d = new EventEmitter<X>();
d.getOrCreateEvents("test2", c => console.log(c));// c is infered to string
d.getOrCreateEvents("test2", c => console.log(c)); // c is infered to number
于 2018-01-21T14:09:11.023 回答