用 T[K] 定义 Map
define Map with T[K]
我目前正在从 JS 过渡到 TS,无法完全理解 keyof
。我找到了 https://github.com/kimamula/TypeScript-definition-of-EventEmitter-with-keyof,现在我正在尝试实现它。一切顺利,直到我打开 'noImplicitAny'.
我在 ts 操场上做了一个 example 来说明我遇到的问题:
在构造函数中无法访问 K
所以我必须显式地创建 Map (arg: any)
才能让它工作。
创建地图时是否有避免使用 any 的解决方案?
问题是您正试图将 (arg: keyof T) => any
分配给 (arg: T[K]) => any
。 keyof T
表示 T
的任何 属性 名称 例如在这个 class:
class X { test: string; test2: number; }
keyof X
等同于 'test' | 'test2'
而 T[K]
和 K extends keyof T
表示 T
的 属性 的类型,名称为 K
,所以对于上面的 class T[K]
可以是 number
或 string
,具体取决于为 K
传递的值
因此,如果您有 Emitter<X>
,您基本上会尝试将 (arg: string | number) => any
分配给 (arg: 'test' | 'test2') => any
,这绝对不是类型安全的。
我的猜测是,您想限制 listener
具有与 class 成员相同的 属性 类型的参数。为此,您应该使用 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
我目前正在从 JS 过渡到 TS,无法完全理解 keyof
。我找到了 https://github.com/kimamula/TypeScript-definition-of-EventEmitter-with-keyof,现在我正在尝试实现它。一切顺利,直到我打开 'noImplicitAny'.
我在 ts 操场上做了一个 example 来说明我遇到的问题:
在构造函数中无法访问 K
所以我必须显式地创建 Map (arg: any)
才能让它工作。
创建地图时是否有避免使用 any 的解决方案?
问题是您正试图将 (arg: keyof T) => any
分配给 (arg: T[K]) => any
。 keyof T
表示 T
的任何 属性 名称 例如在这个 class:
class X { test: string; test2: number; }
keyof X
等同于 'test' | 'test2'
而 T[K]
和 K extends keyof T
表示 T
的 属性 的类型,名称为 K
,所以对于上面的 class T[K]
可以是 number
或 string
,具体取决于为 K
因此,如果您有 Emitter<X>
,您基本上会尝试将 (arg: string | number) => any
分配给 (arg: 'test' | 'test2') => any
,这绝对不是类型安全的。
我的猜测是,您想限制 listener
具有与 class 成员相同的 属性 类型的参数。为此,您应该使用 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