Un emisor de eventos tipado en TypeScript
Un mapa de nombres de evento a payloads vuelve seguros on y emit.
type EventMap = {
run: { lang: string; tpm: number };
cleared: { set: string };
error: Error;
};
class Emitter<Events extends Record<string, unknown>> {
#handlers = new Map<keyof Events, Set<(payload: never) => void>>();
on<K extends keyof Events>(type: K, handler: (payload: Events[K]) => void) {
const set = this.#handlers.get(type) ?? new Set();
set.add(handler as (payload: never) => void);
this.#handlers.set(type, set);
return () => set.delete(handler as (payload: never) => void);
}
emit<K extends keyof Events>(type: K, payload: Events[K]): number {
const set = this.#handlers.get(type);
set?.forEach((handler) => (handler as (p: Events[K]) => void)(payload));
return set?.size ?? 0;
}
}
const bus = new Emitter<EventMap>();
bus.on("run", ({ tpm }) => console.log("tpm", tpm));
console.log(bus.emit("run", { lang: "ts", tpm: 98 }));
// bus.emit("run", { lang: "ts" }); // error: falta tpm
Cómo funciona
- El mapa de eventos es la única fuente de verdad.
K extends keyof Eventsata el payload al nombre.- Un payload equivocado, o un evento desconocido, no compila.
Palabras clave y builtins usados aquí
ErrorEventsMapSetasclassconstextendsnevernumberreturnstringthistype
El intento, en números
- Líneas
- 27
- Caracteres a escribir
- 900
- Tokens
- 280
- Ritmo de tres estrellas
- 110 tpm
Al ritmo de tres estrellas de 110 tokens por minuto, este intento toma unos 153 segundos.
Paso 1 de 2 en Eventos tipados; paso 3 de 8 en Async y módulos.