cf.completefrontend

Write the codeHard

Write a typed event emitter: on and emit should only accept the events, and the arguments, of an event map.

The emitter below works at runtime, but any event name and any arguments compile. Make it generic over an event map, so new Emitter<AppEvents>() checks every on and emit against AppEvents, and listeners get their parameter types without annotations. on returns a function that removes the listener.

Write this
type Listener = (...args: any[]) => void; class Emitter {  private listeners = new Map<string, Set<Listener>>();   on(event: string, listener: Listener): () => void {    const set = this.listeners.get(event) ?? new Set<Listener>();    this.listeners.set(event, set);    set.add(listener);    return () => {      set.delete(listener);    };  }   emit(event: string, ...args: any[]): void {    this.listeners.get(event)?.forEach((listener) => listener(...args));  }} // type AppEvents = { login: [userId: string]; logout: [] };// const events = new Emitter<AppEvents>();// events.on("login", (userId) => {}); // userId: string// events.emit("login", 42);           // should be a type error

Solve it in the editor

The answer

Write it yourself first. Then compare it with a reference solution and the checks it passes.

Checking your sign-in…