export class Signal void> { private readonly handlers = new Set(); add(handler: T): () => void { this.handlers.add(handler); return () => this.remove(handler); } remove(handler: T): void { this.handlers.delete(handler); } emit(...args: Parameters): void { for (const handler of [...this.handlers]) handler(...args); } } export interface CallableSignal void> { (handler: T): () => void; add(handler: T): () => void; once(handler: T): void; remove(handler: T): void; clear(): void; invoke(...args: Parameters): void; invokeAsync(...args: Parameters): Promise; emit(...args: Parameters): void; } export function createSignal void>(): CallableSignal { const handlers = new Set(); const signal = ((handler: T) => signal.add(handler)) as CallableSignal; signal.add = (handler: T) => { handlers.add(handler); return () => signal.remove(handler); }; signal.once = (handler: T) => { const wrapped = ((...args: Parameters) => { signal.remove(wrapped as T); handler(...args); }) as T; signal.add(wrapped); }; signal.remove = (handler: T) => { handlers.delete(handler); }; signal.clear = () => { handlers.clear(); }; signal.invoke = (...args: Parameters) => { signal.emit(...args); }; signal.invokeAsync = async (...args: Parameters) => Promise.all([...handlers].map((handler) => handler(...args))); signal.emit = (...args: Parameters) => { for (const handler of [...handlers]) handler(...args); }; return signal; }