Как создать проект React с TypeScript

Основная идея
JavaScript слабо типизирован. Это удобно, но ошибки часто обнаруживаются только в рантайме. TypeScript добавляет статическую проверку типов поверх JavaScript. В React это помогает ловить ошибки при компиляции и улучшает автодополнение в IDE.
Создание проекта React с TypeScript
Команда create-react-app позволяет создать проект с TypeScript с помощью опции –template.
Чтобы создать новый проект React с TypeScript, выполните:
npx create-react-app app-name --template typescriptЭта команда создаёт каркас проекта с настройками TypeScript. Если вы хотите добавить TypeScript в существующее приложение, переходите в корневую папку проекта и выполните установку зависимостей:
npm install --save typescript @types/node @types/react @types/react-dom @types/jestЗатем замените расширения файлов .js → .tsx для файлов, которые содержат JSX. После этого может появиться ошибка “React refers to a UMD global, but the current file is a module.” Её можно решить, импортируя React в каждом файле или настроив tsconfig.
Быстрое решение через tsconfig
Создайте или отредактируйте файл tsconfig.json и установите jsx в react-jsx:
{
"compilerOptions": {
"jsx": "react-jsx",
"target": "es6",
"module": "esnext"
}
}Это позволяет использовать новый JSX трансформ, когда импорт React не обязателен в каждом файле (при условии соответствующей версии React и компилятора).
Важно: версия React должна поддерживать новый JSX-трансформ (React 17+). Если вы не уверены, безопаснее явно импортировать React.
Создание функционального компонента в TypeScript
Синтаксис компонента похож на JavaScript. Пример простого компонента Greetings:
export default function Greetings() {
return (
Hello world
)
}TypeScript выводит тип возвращаемого значения автоматически. Можно явно указать тип:
export default function Greetings(): JSX.Element {
return (
Hello world
)
}TypeScript выдаст ошибку, если функция вернёт не JSX.Element.
Типизация props в React
Props делают компоненты переиспользуемыми. Пример с inline-типизацией:
function Greetings({name}: {name: string}) {
return (
Hello {name}
)
}Лучше выносить типы отдельно:
type GreetingsProps = {
name: string;
};
function Greetings({name}: GreetingsProps) {
return (
Hello {name}
)
}Если планируете экспортировать и расширять типы, используйте interface:
export interface GreetingsProps {
name: string;
};Интерфейс можно расширить:
import { GreetingsProps } from './Greetings'
interface WelcomeProps extends GreetingsProps {
time: string;
}
function Welcome({name, time}: WelcomeProps) {
return (
Good {time}, {name}!
)
}Для необязательных пропсов используйте ?:
interface GreetingsProps {
name?: string;
};Если name не передан, TypeScript не будет жаловаться. Однако продумайте значения по умолчанию и поведение компонента без пропса.
Использование состояния с useState
Часто TypeScript выводит тип состояния по значению по умолчанию:
const [customerName, setCustomerName] = useState("");Если значение нельзя инициализировать сразу, нужно задавать тип явно:
const [customerName, setCustomerName] = useState("");
const [age, setAge] = useState(0);
const [isSubscribed, setIsSubscribed] = useState(false); Можно использовать интерфейс для сложного состояния:
interface ICustomer {
customerName: string;
age: number;
isSubscribed: boolean;
}
const [customer, setCustomer] = useState({
customerName: "Jane",
age: 10,
isSubscribed: false
}); Если состояние может быть undefined, указывайте объединение типов: useState
Типизация событий
События важны для взаимодействия с пользователем. В TypeScript вы можете типизировать параметры обработчиков.
Пример компонента Login без типизации (JavaScript):
import { useState } from 'react';
export default function Login() {
const [email, setEmail] = useState('');
const handleChange = (event) => {
setEmail(event.target.value);
};
const handleClick = (event) => {
console.log('Submitted!');
};
return (
);
}TypeScript требует типов для event или обработчика. Для input используйте ChangeEvent с указанием DOM-элемента:
import { ChangeEvent, useState } from 'react';
const handleChange = (event: ChangeEvent) => {
setEmail(event.target.value);
}; Можно типизировать сам обработчик через ChangeEventHandler:
import { ChangeEventHandler, useState } from 'react';
const handleChange: ChangeEventHandler = (event) => {
setEmail(event.target.value);
}; Для кликов используйте MouseEvent или MouseEventHandler:
import { MouseEvent, MouseEventHandler } from 'react';
const handleClick = (event: MouseEvent) => {
console.log('Submitted!');
};
const handleClick2: MouseEventHandler = (event) => {
console.log('Submitted!');
};Полный список типов событий и рекомендации см. в React TypeScript cheat sheet.
Для больших форм имеет смысл использовать библиотеку, например Formik или React Hook Form, которые хорошо совместимы с TypeScript.
Частые ошибки и как их избегать
- Неявный any. Избегайте any, если это возможно. any отключает проверку типов.
- Неправильное расширение файлов. JSX-файлы должны быть .tsx, обычные модули — .ts.
- Несовместимость версий React/TypeScript/TSX-трансформа. Проверяйте минимальные версии в changelog.
- Отсутствие типов для сторонних библиотек. Используйте @types/имябиблиотеки или указывайте свои объявления в .d.ts.
Важно: при миграции больших кодовых баз переходите постепенно. Начните с ключевых модулей, добавляйте типы для публичных API и подключайте строгие опции TypeScript последовательно.
Лучшие практики
- Начинайте с негрубых правил: strict: false — затем шаг за шагом усиливайте проверки.
- Используйте eslint + typescript-eslint для единообразия кода.
- Выносите типы и интерфейсы в отдельные файлы, чтобы улучшить повторное использование.
- Пишите небольшие интерфейсы вместо глубоких union-типов там, где это уместно.
- Пишите unit-тесты для критичных компонентов.
Альтернативные подходы
- Flow — статическая типизация от Facebook, но сейчас TypeScript имеет более широкую экосистему.
- JSDoc + проверка типов — если вы хотите оставаться на .js, можно использовать JSDoc-комментарии и проверку с помощью tsc.
- Полуавтоматическая миграция — использовать @ts-ignore временно для больших участков и постепенно удалять их.
Рольные чеклисты
Разработчик:
- Установить зависимости TypeScript и @types.
- Переименовать .js → .tsx по мере необходимости.
- Запустить сборку и исправить ошибки типов.
Технический руководитель:
- Определить стратегию миграции (big-bang vs incremental).
- Настроить CI для проверки типов.
- Включить eslint и правила проектной команды.
QA / Тестировщик:
- Проверить критичные UI-пути при изменениях типов.
- Свернуть регрессионные тесты после миграции.
Малогабаритный чек-лист приёмки
Критерии приёмки
- Проект собирается без ошибок типов.
- Критичные компоненты работают в браузере как до миграции.
- CI выполняет tsc –noEmit и проходит.
Краткая методология миграции
- Установить TypeScript и @types.
- Включить базовый tsconfig и запустить tsc для выявления ошибок.
- Переименовывать файлы по приоритету функциональности.
- Исправлять типы по мере появления ошибок.
- Постепенно включать более строгие проверки compilerOptions.
Небольшая шпаргалка
- Команда создания: npx create-react-app my-app –template typescript
- Добавить в проект: npm i typescript @types/react @types/react-dom
- Общий паттерн props: type XProps = { … } и function X(props: XProps)
- useState тип: const [s, setS] = useState
(undefined) - Событие input: (e: ChangeEvent
) => void
1‑строчный глоссарий
- TypeScript — надстройка над JavaScript для статической типизации.
- JSX — синтаксис разметки в JavaScript для React.
- TSX — файл TypeScript, содержащий JSX.
- props — параметры компонента.
- useState — хук состояния в функциональных компонентах.
Заключение
TypeScript делает код React более предсказуемым и удобным для сопровождения. Первые шаги требуют усилий, но отдача проявляется в снижении багов и улучшении DX (developer experience).
Краткое резюме:
- Начните с создания нового проекта через шаблон или постепенной миграции.
- Типизируйте props, состояние и события.
- Настройте tsconfig и CI для проверки типов.
Важно: не пытайтесь сразу включить самые строгие правила. Мигрируйте поэтапно.
Summary:
- TypeScript повышает надёжность React-приложений.
- Миграция возможна для новых и существующих проектов.
- Используйте интерфейсы и типы для ясных контрактов между компонентами.
Похожие материалы
RDP: полный гид по настройке и безопасности
Android как клавиатура и трекпад для Windows
Советы и приёмы для работы с PDF
Calibration в Lightroom Classic: как и когда использовать
Отключить Siri Suggestions на iPhone