I'm trying to make a typesafe EventEmitter, however I cannot enforce that the interface passed to the generic is of type EventMap
without TypeScript complaining.
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> {}
Gives me
Type 'TestEvents' does not satisfy the constraint 'Record<string, EventHandler>'.
Index signature is missing in type 'TestEvents'.