export interface Listener { (event: T): any; } export interface Disposable { dispose(): void; } /** passes through events as they happen. You will not get events from before you start listening */ export class TypedEvent { private listeners: Listener[] = []; private listenersOncer: Listener[] = []; on = (listener: Listener): Disposable => { this.listeners.push(listener); return { dispose: () => this.off(listener), }; }; once = (listener: Listener): void => { this.listenersOncer.push(listener); }; off = (listener: Listener) => { const callbackIndex = this.listeners.indexOf(listener); if (callbackIndex > -1) this.listeners.splice(callbackIndex, 1); }; emit = (event: T) => { /** Update any general listeners */ this.listeners.forEach(listener => listener(event)); /** Clear the `once` queue */ this.listenersOncer.forEach(listener => listener(event)); this.listenersOncer = []; }; pipe = (te: TypedEvent): Disposable => this.on(e => te.emit(e)); }