TypeScript и React
Дальше: TypeScript и Node.js · События · Асинхронность · Справочник — интеграция с фреймворками
React описывает UI как функции от состояния. TypeScript добавляет контракты — какие props обязательны, что лежит в state, какие поля пришли с API. Это снижает поломки при рефакторинге компонентов и согласует фронт с backend-DTO. Удобный порядок — типы и типизация, асинхронность, эта статья, обработка ошибок.
Курс по React: справочник 271. Старт проекта — Первая программа на TypeScript +
npm create vite@latest -- --template react-ts.
Интеграция с фреймворками (обзор)
Эта статья — React; общая картина Справочник — интеграция с фреймворками:
| Стек | Шаблон / типы | Учебный материал |
|---|---|---|
| React | react-ts, @types/react | эта статья, Справочник по React |
| Vue | vue-tsc, defineComponent | Справочник по Vue.js |
| Angular | встроенный TS, strict templates | Справочник по Angular |
| Node.js | @types/node, DTO API | TypeScript и Node.js |
Общие принципы для всех — типизировать props/inputs, ответы API, состояния загрузки (discriminated union) — Типы данных и типизация в TypeScript, Асинхронное программирование в TypeScript.
TypeScript в React-проектах
| Без TS | С TS |
|---|---|
Опечатка в props — в runtime | Ошибка при сборке / в IDE |
| Неверное поле от API | Подсветка при доступе |
| Рефакторинг prop name | Find references + компилятор |
useState(null) — любой тип | useState<User | null>(null) |
TypeScript не заменяет тесты и не валидирует JSON с сервера сам — для API нужны guards или Zod — Рекомендации по разработке на TypeScript, Асинхронное программирование в TypeScript.
Старт — Vite + React + TS
npm create vite@latest my-app -- --template react-ts
cd my-app && npm install && npm run dev
Разбор:
- Шаблон даёт
tsconfig.app.json, типы React, ESLint. - Сборку делает Vite; типы проверяют
tsc -b(вpackage.jsonчасто в скриптеbuildпередvite build). Отдельно для CI удобноtsc --noEmit.
Структура типов:
src/
├── components/
├── types/
│ └── api.ts # DTO и LoadState
└── App.tsx
Компонент и props
Код ITЗагрузка примера кода…
Разбор:
children?: React.ReactNode— текст, элемент, массив,null.- Не обязательно
React.FC— явный тип props у функции читаемее; в Справочник по TypeScript описаны варианты.
Расширение props нативного элемента
type ButtonProps = {
label: string;
} & React.ButtonHTMLAttributes<HTMLButtonElement>;
function Button({ label, ...rest }: ButtonProps) {
return <button type="button" {...rest}>{label}</button>;
}
Разбор:
...restпробрасываетonClick,disabled,classNameс проверкой типов.
Типизация UI-компонентов
Сниппеты из Uiverse / Galaxy — это HTML+CSS. В React/Vue те же блоки оформляют props и discriminated unions, чтобы варианты кнопки, поля и переключателя не смешивались.
Код ITЗагрузка примера кода…
Поле ввода с ошибкой с сервера:
Код ITЗагрузка примера кода…
Тип переключателя (checkbox, radio или switch) — union, чтобы не перепутать API:
type ToggleControl =
| { kind: 'checkbox'; checked: boolean; onChange: (v: boolean) => void; label: string }
| { kind: 'radio'; name: string; value: string; checked: boolean; label: string }
| { kind: 'switch'; checked: boolean; onChange: (v: boolean) => void; label: string };
Стили из Типовых элементов интерфейса подключают через CSS Modules или глобальный класс; логика остаётся в TypeScript.
Готовые файлы Button.tsx, ProfileCard.tsx, ThemeSwitch.tsx, Tooltip.tsx с разбором — React — UI на TypeScript.
useState с явным типом
type User = { id: string; name: string };
function UserBadge() {
const [user, setUser] = React.useState<User | null>(null);
if (!user) return <p>Не авторизован</p>;
return <span>{user.name}</span>;
}
Разбор:
useState(null)без generic в strict даёт толькоnull— укажитеUser | null.- Обновление:
setUser({ id: "1", name: "Ann" })проверяется на соответствиеUser.
LoadState в компоненте
Тот же discriminated union, что в Асинхронное программирование в TypeScript:
Код ITЗагрузка примера кода…
Разбор:
cancelledв cleanup — защита от setState после размонтирования.switchпоstatusсужает тип без лишних флаговisLoading.
useReducer с типизированными actions
Когда состояние и переходы сложнее, чем один setState, удобен discriminated union для действий:
Код ITЗагрузка примера кода…
Разбор:
CartAction— union с полемtype; в веткеswitchдоступны только нужные поля (skuвadd).dispatch({ type: "addd", sku: "x" })— ошибка компиляции (опечатка вtype).- Тот же приём, что для
LoadState, но для событий UI — Паттерны в TypeScript.
ComponentProps — переиспользование props
Не дублируйте поля нативного элемента — возьмите тип у готового компонента или HTML-тега:
Код ITЗагрузка примера кода…
Разбор:
ComponentProps<"button">— все допустимые props<button>с типами событий.Pickоставляет в публичном API только нужные поля обёртки.
События форм
Код ITЗагрузка примера кода…
| Тип события | Элемент |
|---|---|
ChangeEvent<HTMLInputElement> | <input> |
ChangeEvent<HTMLSelectElement> | <select> |
FormEvent<HTMLFormElement> | <form onSubmit> |
MouseEvent<HTMLButtonElement> | <button onClick> |
Подробнее DOM — События и обработка событий в TypeScript.
useRef и DOM
function FocusInput() {
const ref = React.useRef<HTMLInputElement>(null);
const focus = () => ref.current?.focus();
return (
<>
<input ref={ref} />
<button type="button" onClick={focus}>Фокус</button>
</>
);
}
Разбор:
ref.currentимеет типHTMLInputElement | null— нужен optional chaining.
Контекст с типом
Код ITЗагрузка примера кода…
Разбор:
nullпо умолчанию заставляет проверять провайдер в хуке.- Альтернатива — значение по умолчанию в
createContext(менее строго).
Слой типов API
src/types/api.ts:
export type UserDto = { id: string; name: string; email: string };
export type CreateUserBody = Pick<UserDto, "name" | "email">;
Компонент импортирует только типы:
import type { UserDto } from "../types/api.js";
Разбор:
- DTO ≠ domain: на границе сети — отдельные типы — Рекомендации по разработке на TypeScript, TypeScript и Node.js.
import typeне попадает в JS-бандл.
Дженерики в компонентах
Код ITЗагрузка примера кода…
Частые ошибки
| Ошибка | Что делать |
|---|---|
props: any | явный type Props |
as User на json() | unknown + guard |
Разрозненные loading/error | LoadState union |
Забыли children в типе | React.ReactNode |
React.FC с implicit children | явные props (стиль команды) |
| Типы API в каждом файле | types/api.ts |
Практика
- Создайте
react-tsпроект и компонентCardс typed props. - Реализуйте
ProfileсLoadStateиisUserguard. - Форма с
onSubmitиChangeEvent<HTMLInputElement>. - Вынесите
UserDtoвtypes/api.ts, используйтеimport type. - Добавьте generic
List<T>для массива задач. - Перепишите локальное состояние корзины на
useReducerс union actions.
Смежные статьи
- Асинхронность · События · Ошибки
- Простые приложения · Паттерны
- Синтаксис —
.tsx,import type - Справочник по React · Справочник — интеграция с фреймворками