类型安全的事件系统
构建类型安全的事件发射器
1. 基础事件系统
type EventMap = {
click: { x: number; y: number };
change: { value: string };
submit: {};
};
class EventEmitter<Events extends Record<string, any>> {
private listeners = new Map<keyof Events, Set<Function>>();
on<K extends keyof Events>(event: K, listener: (payload: Events[K]) => void): () => void {
if (!this.listeners.has(event)) {
this.listeners.set(event, new Set());
}
this.listeners.get(event)!.add(listener);
return () => this.listeners.get(event)?.delete(listener);
}
emit<K extends keyof Events>(event: K, payload: Events[K]): void {
this.listeners.get(event)?.forEach((fn) => fn(payload));
}
off<K extends keyof Events>(event: K, listener: (payload: Events[K]) => void): void {
this.listeners.get(event)?.delete(listener);
}
}
const emitter = new EventEmitter<EventMap>();
emitter.on('click', ({ x, y }) => console.log(x, y));
emitter.emit('click', { x: 100, y: 200 });
2. 异步事件
class AsyncEventEmitter<Events extends Record<string, any>> {
private listeners = new Map<keyof Events, Set<Function>>();
async emit<K extends keyof Events>(event: K, payload: Events[K]): Promise<void> {
const fns = this.listeners.get(event);
if (fns) await Promise.all([...fns].map((fn) => fn(payload)));
}
}
3. 类型安全的事件构建器
type EventBuilder = {
[K in string]: any;
};
function defineEvents<E extends EventBuilder>() {
return {
createEmitter: () => new EventEmitter<E>(),
on: <K extends keyof E & string>(
emitter: EventEmitter<E>,
event: K,
listener: (payload: E[K]) => void
) => emitter.on(event, listener),
};
}