ПрограммированиеFrontend разработчик

Как реализовать типизацию пользовательских событий (custom events) в TypeScript? Какие нюансы следует учитывать при работе с event-объектами и передачей данных?

Проходите собеседования с ИИ помощником Hintsage

Ответ.

TypeScript позволяет типизировать собственные события, чтобы гарантировать корректную работу с их объектами, особенно в веб-приложениях или при работе с паттерном pub/sub. Для типизации событий часто используют тип CustomEvent с параметизированным generic-типом:

interface MyEventDetail { username: string; age: number; } const event = new CustomEvent<MyEventDetail>('user:create', { detail: { username: 'alice', age: 30 } }); document.addEventListener('user:create', (e: CustomEvent<MyEventDetail>) => { console.log(e.detail.username); });

Ключевые нюансы:

  • Нужно убедиться, что используемый тип события (CustomEvent<T>) совпадает как при создании события, так и при его обработке.
  • Если используется нативное событие, применяйте основные типы событий, а не any или object.
  • Не забывайте о наследовании событий, если создаёте собственные типы.

Вопрос с подвохом.

Часто спрашивают: «Можно ли типизировать объект event напрямую как CustomEvent<Type> в обработчике, если событие создаёт сторонняя библиотека?»

Правильный ответ: Только если абсолютно точно известно, что библиотека генерирует события через CustomEvent с дженериком. Иначе типизация будет некорректной, возможны runtime-ошибки.

Пример:

document.addEventListener('some-event', (e: Event) => { // Ошибочно: 'e' не обязательно CustomEvent const detail = (e as CustomEvent<{ id: number }>).detail; // Это приведёт к ошибке, если событие не CustomEvent });

Примеры реальных ошибок из-за незнания тонкостей темы.


История

На проекте использовали абстракцию pub/sub и бросали события через простой Event вместо CustomEvent. Ожидали, что можно будет обращаться к event.detail, но у базового Event такого поля нет, что привело к бесшумному undefined и трудноуловимым багам.


История

Часть команды типизировала кастомные события через any, чтобы "быстрее" внедрить обработчики на разные сценарии. В результате, позже стали возникать ошибки из-за передачи разных структур данных через detail, а TypeScript не сигнализировал о несоответствиях.


История

В одном проекте стали использовать типизацию событий как CustomEvent<string>, передавая при этом сложные объекты через detail. По ошибке сериализовали detail, что приводило к необходимости делать дополнительный JSON.parse на стороне обработчика и к утрате типизации внутри TypeScript.