我正在尝试制作一个类型安全的 EventEmitter,但是我不能强制传递给泛型的接口是类型EventMap
而不是 TypeScript 抱怨的。
type EventHandler = () => void
type EventMap = Record<string, EventHandler>
interface EventListener {
handler: EventHandler
once: boolean
}
export class Emitter<Events extends EventMap> {
private listeners = new Map<keyof Events, EventListener[]>()
private addListener<E extends keyof EventMap>(type: E, listener: EventListener) {
const listeners = this.listeners.get(type) || []
this.listeners.set(type, [...listeners, listener])
}
@bind
public on<E extends keyof EventMap>(type: E, handler: Events[E]) {
this.addListener(type, { handler, once: false })
}
}
interface TestEvents {
test: (a: number) => void,
}
class Test extends Emitter<TestEvents> {}
给我
Type 'TestEvents' does not satisfy the constraint 'Record<string, EventHandler>'.
Index signature is missing in type 'TestEvents'.
你需要限制它有点不同,你想要的所有键Events
是EventHandlers
不一定是Events
有一个指数的签名。您可以使用以下内容:
type EventHandler = (...a: any[]) => void
interface EventListener {
handler: EventHandler
once: boolean
}
export class Emitter<Events extends Record<keyof Events, EventHandler>> {
private listeners = new Map<keyof Events, EventListener[]>()
private addListener<E extends keyof Events>(type: E, listener: EventListener) {
const listeners = this.listeners.get(type) || []
this.listeners.set(type, [...listeners, listener])
}
public on<E extends keyof Events>(type: E, handler: Events[E]) {
this.addListener(type, { handler, once: false })
}
}
interface TestEvents {
test: (a: number) => void,
}
class Test extends Emitter<TestEvents> { }
new Test().on("test", a => a.toExponential) // a is number.
但是,这种方法存在问题,如果地图中有多个事件(您可能会),则打字稿将无法推断参数类型
interface TestEvents {
test: (a: number) => void,
test2: (a: number) => void,
}
class Test extends Emitter<TestEvents> { }
new Test().on("test", a => a.toExponential) // a is any
这是可以修复的,但类型变得更复杂,请参阅此处以获取非常相似的想法。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句