События и обработка событий в TypeScript
Дальше: TypeScript и React · Ветвления · События в JavaScript
В браузере UI строится на событиях (click, input, submit) — сигналах о действии пользователя или изменении DOM. TypeScript задаёт конкретный тип события — доступны правильные поля (value, clientX, preventDefault). В React используются синтетические обёртки — TypeScript и React. Удобный порядок — синтаксис, эта статья, TypeScript и React.
Подробная модель DOM и bubbling — события в JavaScript. Таблицы глобалов — Справочник — DOM и окружение.
Окружение и глобальные типы
TypeScript знает браузерные API через lib в tsconfig:
{
"compilerOptions": {
"lib": ["ES2022", "DOM", "DOM.Iterable"]
}
}
| Окружение | Типичный lib / пакет |
|---|---|
| Браузер | DOM, DOM.Iterable |
| Node.js | @types/node (без DOM) |
| Тесты (jsdom) | DOM + настройки test runner |
Глобалы вроде document, window, fetch появляются из lib, без объявления в вашем коде. Для своих глобалов (версия сборки, фичефлаги) — declare const в global.d.ts — 9.md §декларации.
Node-окружение (process, Buffer) типизируется через @types/node — TypeScript и Node.js.
Базовый обработчик
const button = document.querySelector("button");
if (!(button instanceof HTMLButtonElement)) {
throw new Error("Button not found");
}
button.addEventListener("click", (e: MouseEvent) => {
console.log(e.clientX, e.clientY);
});
Разбор:
querySelectorвозвращаетElement | null— сужайте черезinstanceof— Операторы и условные ветвления в TypeScript.- Для
clickна кнопке —MouseEvent, вместо общегоEvent.
Типы DOM-событий
| Событие | Тип |
|---|---|
click на элементе | MouseEvent |
input / change на <input> | Event или InputEvent |
input на <input type="text"> | лучше через target |
submit на <form> | SubmitEvent |
keydown | KeyboardEvent |
Код ITЗагрузка примера кода…
Разбор:
- В
inputlistenerinput.valueуже типизирован послеinstanceof. - Альтернатива:
(e.target as HTMLInputElement).value— слабее.
currentTarget и target
list.addEventListener("click", (e: MouseEvent) => {
const target = e.target;
if (!(target instanceof HTMLElement)) return;
const item = target.closest("[data-id]");
if (!item) return;
const id = item.getAttribute("data-id");
console.log("clicked", id);
});
Разбор:
- Делегирование: один listener на списке, клик по дочерним элементам.
closestищет предка с атрибутом.
Клавиатура
window.addEventListener("keydown", (e: KeyboardEvent) => {
if (e.ctrlKey && e.key === "s") {
e.preventDefault();
console.log("Save shortcut");
}
});
Пользовательские события
Код ITЗагрузка примера кода…
Разбор:
- Generic у
CustomEvent<T>зависит от lib DOM; иногдаdetailтипизируют вручную после проверки. - Typed emitter в приложении — Паттерны в TypeScript.
React — кратко
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValue(e.target.value);
};
События React не нативные MouseEvent — обёртки с похожим API. Не смешивайте addEventListener и React на одном узле без причины.
Частые ошибки
| Ошибка | Что делать |
|---|---|
(e: Event) везде | конкретный тип |
as HTMLInputElement без проверки | instanceof |
Забыли preventDefault на submit | перезагрузка страницы |
onclick в HTML | addEventListener в TS-модуле |
Практика
- Форма —
input,submit, вывод ошибок валидации. - Горячая клавиша
Ctrl+SсKeyboardEvent. CustomEventсdetailи подписчик.- Делегирование клика по списку
data-id. - Тот же сценарий в React — TypeScript и React.