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.apply(this, args)); } invokeAsync(...args: FunctionParameters) { return Promise.all(this.handlers.map((handler) => handler.apply(this, 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>() : { once: (cb: CallbackSignature) => void; remove: (cb: CallbackSignature) => void, invoke: (...args: FunctionParameters) => void, invokeAsync: (...args: FunctionParameters) => Promise, clear: () => void, } & ((this: any, cb: CallbackSignature) => EventEmitter ) { 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 (this: any, ...args: any[]) { cb.apply(this, 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; }