Код Middle Классы и интерфейсы спрашивают часто обновлено

Типизированный EventEmitter с картой событий

Условие

Напиши класс TypedEmitter<Events extends Record<string, unknown[]>>, где Events это карта «имя события → кортеж аргументов». Методы:

  • on<E extends keyof Events>(event: E, fn: (...args: Events[E]) => void): () => void: подписка, возвращает функцию отписки;
  • emit<E extends keyof Events>(event: E, ...args: Events[E]): number: синхронно вызывает слушателей, возвращает их число.

Так emit('order:paid', 'id') без суммы не скомпилируется. run(ops) в заготовке гоняет сценарий: каждая операция ['emit', id, amount] или ['off'] (отписать первого слушателя).

Примеры

run([["emit", "A1", 500]]) // ["mail A1 500", "crm A1", "listeners 2"]
run([["off"], ["emit", "B2", 10]]) // ["crm B2", "listeners 1"]
run([["emit", "C", 1], ["off"], ["off"], ["emit", "D", 2]]) // ["mail C 1", "crm C", "listeners 2", "crm D", "listeners 1"]

Как подойти

Подсказки: 2
  1. Хранилище слушателей: mapped-тип { [E in keyof Events]?: ((...args: Events[E]) => void)[] }.
  2. Кортежи с метками ([orderId: string, amount: number]) дают имена параметров в подсказках IDE.

Решите в тренажёре

Редактор с автотестами прямо в браузере. Можно решить спокойно, вслух или под таймером, как на собесе.