← Усі задачіTypeScript · Middle
Типізований EventEmitter
Клас Emitter<Events> отримує опис подій: new Emitter<{ login: { userId: number }; message: string }>(). Метод on(event, handler) підписує обробник і повертає функцію відписки, emit(event, payload) викликає обробники цієї події.
Зробіть типи точними: назва події - лише одна з ключів Events, а тип payload в обробнику та в emit береться з опису саме цієї події.
Ctrl+Enter - запустити тести. Tab - відступ; щоб вийти з редактора клавіатурою, натисніть Esc, а потім Tab. Код зберігається в цьому браузері.
Тести (7)
Тести типів перевіряє компілятор TypeScript у режимі strict. Expect<Equal<A, B>> проходить, коли типи збігаються точно, а // @ts-expect-error - коли наступний рядок не компілюється. Перший запуск завантажує компілятор, тож триває кілька секунд.
- типи
type E = { login: { userId: number }; message: string }; const e = new Emitter<E>(); e.on('login', (payload) => { type _ = Expect<Equal<typeof payload, { userId: number }>>; });
- типи
type E = { login: { userId: number }; message: string }; const e = new Emitter<E>(); // @ts-expect-error - message carries a string e.emit('message', 42);
- типи
type E = { login: { userId: number }; message: string }; const e = new Emitter<E>(); // @ts-expect-error - there is no such event e.on('signup', () => {});
const e = new Emitter(); const a = fn(); const b = fn(); e.on('message', a); e.on('message', b); e.emit('message', 'hi'); expect(a).toHaveBeenCalledWith('hi'); expect(b).toHaveBeenCalledWith('hi');
const e = new Emitter(); const h = fn(); const off = e.on('login', h); e.emit('login', { userId: 1 }); off(); e.emit('login', { userId: 2 }); expect(h).toHaveBeenCalledTimes(1); expect(h).toHaveBeenLastCalledWith({ userId: 1 });
const e = new Emitter(); expect(() => e.emit('nobody-listens', 1)).not.toThrow();
const e = new Emitter(); const a = fn(); const b = fn(); e.on('x', a); e.on('y', b); e.emit('x', 1); expect(a).toHaveBeenCalledTimes(1); expect(b).toHaveBeenCalledTimes(0);