TypeScript: типизация событий и обработчиков
Правильная типизация обработчиков событий DOM и кастомных событий. Работа с MouseEvent, KeyboardEvent и создание типобезопасных компонентов.
Типизация событий и обработчиков помогает избежать ошибок при работе с DOM и создании компонентов.
Типизация обработчика клика
// Типизация обработчика события
type ButtonClickHandler = (event: MouseEvent) => void;
// Компонент с типизированным обработчиком
interface ButtonProps {
label: string;
onClick: ButtonClickHandler;
disabled?: boolean;
}
function Button({ label, onClick, disabled = false }: ButtonProps) {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
}
// Использование
const handleClick = (event: MouseEvent) => {
console.log("Clicked!", event.target);
};
<Button
label="Submit"
onClick={handleClick}
disabled={false}
/>
Типизация клавиатурных событий
type KeyboardHandler = (event: KeyboardEvent) => void;
interface InputProps {
value: string;
onChange: (value: string) => void;
onKeyDown?: KeyboardHandler;
placeholder?: string;
}
function Input({ value, onChange, onKeyDown, placeholder }: InputProps) {
const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
if (onKeyDown) {
onKeyDown(event);
}
// Проверка конкретных клавиш
if (event.key === 'Enter') {
// Обработка Enter
}
};
return (
<input
value={value}
onChange={(e) => onChange(e.target.value)}
onKeyDown={handleKeyDown}
placeholder={placeholder}
/>
);
}
Типизация кастомных событий
// Определяем тип кастомного события
interface CustomEvent<T = any> {
type: string;
detail: T;
timestamp: number;
}
// Тип обработчика кастомного события
type CustomEventHandler<T> = (event: CustomEvent<T>) => void;
// Пример использования
interface UserCreatedEvent {
userId: number;
userName: string;
}
const handleUserCreated: CustomEventHandler<UserCreatedEvent> = (event) => {
console.log(`User ${event.detail.userName} created at ${event.timestamp}`);
};
Типизация событий формы
type FormSubmitHandler = (event: FormEvent<HTMLFormElement>) => void;
type InputChangeHandler = (event: ChangeEvent<HTMLInputElement>) => void;
interface FormProps {
onSubmit: FormSubmitHandler;
children: React.ReactNode;
}
function Form({ onSubmit, children }: FormProps) {
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
onSubmit(event);
};
return <form onSubmit={handleSubmit}>{children}</form>;
}
Типизация событий с данными
interface EventWithData<T> {
originalEvent: Event;
data: T;
}
type DataEventHandler<T> = (event: EventWithData<T>) => void;
// Использование
interface ProductData {
id: number;
name: string;
}
const handleProductSelect: DataEventHandler<ProductData> = (event) => {
console.log('Selected product:', event.data.name);
// event.originalEvent содержит оригинальное событие
};
Типизация обработчиков с опциональными параметрами
interface ComponentProps {
onClick?: (event: MouseEvent) => void;
onHover?: (event: MouseEvent) => void;
onFocus?: (event: FocusEvent) => void;
}
function Component({ onClick, onHover, onFocus }: ComponentProps) {
return (
<div
onClick={onClick}
onMouseEnter={onHover}
onFocus={onFocus}
>
Content
</div>
);
}
Usage:
Всегда типизируй обработчики событий. Это даёт автодополнение, проверку типов и предотвращает ошибки в рантайме.
Notes:
⚠️ Используй конкретные типы событий (MouseEvent, KeyboardEvent) вместо общего Event. TypeScript предоставляет типы для всех стандартных DOM-событий. Для React используй типы из @types/react.