type FunctionParameters any> = T extends (...args: infer P) => any ? P : never; export class EventEmitter any> { handlers: Array = []; register(cb: CallbackSignature, once: boolean = false) { this.handlers.push(cb); return this; } invoke(...args: FunctionParameters) { this.handlers.forEach((handler) => handler(...args)); } invokeAsync(...args: FunctionParameters) { return Promise.all(this.handlers.map((handler) => handler(...args))); } remove (cb: CallbackSignature) { const index = this.handlers.indexOf(cb); this.handlers[index] = this.handlers[this.handlers.length - 1]; this.handlers.pop(); } clear() { this.handlers = []; } } export function createSignal void | Promise>() { const emitter = new EventEmitter(); function register(this: any, cb: CallbackSignature): EventEmitter { return emitter.register(cb, this === null); }; register.once = (cb: CallbackSignature) => { const callback: any = function (...args: any[]) { cb(...args); emitter.remove(callback); } emitter.register(callback); } register.remove = (cb: CallbackSignature) => emitter.remove(cb) register.invoke = (...args: FunctionParameters) => emitter.invoke(...args); register.invokeAsync = (...args: FunctionParameters) => emitter.invokeAsync(...args); register.clear = () => emitter.clear(); return register; }