type EventMap = Record; type EventKey = string & keyof T; type EventReceiver = (params: T) => void; export class Emitter { private listeners: { [K in keyof EventMap]?: Array<(p: EventMap[K]) => void>; } = {}; on>(eventName: K, fn: EventReceiver): void { this.listeners[eventName] = (this.listeners[eventName] || []).concat(fn); } off>(eventName: K, fn: EventReceiver): void { this.listeners[eventName] = (this.listeners[eventName] || []).filter( (f) => f !== fn ); } emit>(eventName: K, params: T[K]): void { (this.listeners[eventName] || []).forEach((fn) => { fn(params); }); } }