Использование TypeScript в связке с React стало стандартом индустрии, позволяя создавать более предсказуемый и безопасный код. В новом обучающем руководстве от freeCodeCamp Рэйчел Джонсон, преподаватель платформы Scrimba, детально разбирает процесс перевода существующего React-проекта на TypeScript, охватывая всё — от типизации хуков useState до работы с функциональными пропсами и утилитами типов .
🛠️ Настройка проекта и переход на TypeScript 1:51
Процесс начинается с настройки рабочего окружения. Рэйчел Джонсон утверждает, что ручная установка TypeScript в существующий проект — это трудоемкий процесс, требующий сложной конфигурации tsconfig.json, установки множества пакетов и переименования файлов . В качестве наиболее «чистого и безопасного» пути она рекомендует использовать сборщик Vite.
Для создания проекта используются следующие команды в терминале:
npm create vite— инициализация проекта .- Выбор фреймворка: React.
- Выбор варианта: TypeScript.
npm install— установка зависимостей.
Автор обращает внимание на структуру конфигурационных файлов. В проекте на Vite файл tsconfig.json часто ссылается на другие конфигурации, такие как tsconfig.app.json и tsconfig.node.json, что позволяет гибко настраивать поведение TypeScript для разных частей приложения . Также важными являются пакеты @types/react и @types/react-dom, которые обеспечивают декларации типов для стандартных библиотек React .
📝 Базовая типизация данных и функций 5:02
Прежде чем переходить к компонентам, необходимо типизировать базовые данные. В примере с игрой «Assembly Endgame» используются массивы слов и объектов языков программирования.
Джонсон демонстрирует два способа типизации массивов объектов :
- Инлайновая типизация: описание структуры объекта прямо в определении массива.
- Кастомные типы (рекомендуемый способ): создание именованного типа через ключевое слово
type. Например,type Language = { name: string; backgroundColor: string; color: string; }.
При работе с функциями в файле utils.ts важно указывать не только типы аргументов, но и тип возвращаемого значения. Если функция генерирует случайный индекс, она должна возвращать number . Если функция принимает название языка для вывода сообщения, аргумент должен быть string . В случаях, когда функция ничего не возвращает (например, только обновляет состояние), автор советует использовать тип void для явного указания намерений программиста .
⚓ Глубокое погружение в useState и Generic-типы 14:07
Хук useState в React умеет выводить типы автоматически на основе начального значения. Однако, по мнению Рэйчел Джонсон, лучше использовать явную типизацию, чтобы сделать код максимально устойчивым к ошибкам .
Для этого используются «дженерики» (Generics) — угловые скобки после названия хука:
useState<string>("")— для строк.useState<string[]>([])— для массивов строк. Без явного указания пустой массив будет типизирован какany[], что лишает TypeScript смысла .
Джонсон объясняет, что под капотом useState настроен на получение типа через дженерик, который затем автоматически применяется и к текущему значению (getter), и к функции обновления (setter) . Это позволяет избежать ситуаций, когда в состояние по ошибке пытаются записать данные неверного типа, например, boolean вместо string .
🧩 Типизация React-компонентов: JSX.Element vs React.FC 25:12
Одной из ключевых тем урока стала типизация самих функциональных компонентов. Рэйчел Джонсон отмечает, что TypeScript обычно сам понимает, что функция возвращает JSX, но в больших проектах полезна явная аннотация.
Существует два основных подхода:
- Аннотация возвращаемого значения
JSX.Element: автор предпочитает именно этот метод . - Использование
React.FC(илиFunctionComponent): этот тип автоматически включаетchildrenв пропсы, даже если они не используются. По словам ведущей, современные разработчики чаще выбираютJSX.Elementиз-за более строгого контроля над дочерними элементами и пропсами по умолчанию .
В случаях, когда компонент может возвращать пустоту (условный рендеринг), используется объединение типов (Union types): JSX.Element | null . Это критично для компонентов вроде контейнера конфетти, который отображается только при победе .
📋 Работа с пропсами и утилитами типов 29:24
Для типизации пропсов рекомендуется создавать отдельный тип для каждого компонента, следуя соглашению об именовании: [ComponentName]Props .
В сложных случаях, когда нужно передать только часть свойств существующего типа, на помощь приходят служебные типы TypeScript. Рэйчел демонстрирует использование Omit :
type StylesProps = Omit<Language, "name">— это позволяет создать тип, который включает все свойстваLanguage, кроме имени .
Особое внимание уделено функциональным пропсам (callback-функциям). Их синтаксис в TypeScript выглядит как стрелочная функция: onAction: (param: string) => void . Если функция не принимает аргументов и ничего не возвращает, она записывается как () => void .
В завершение урока Джонсон подчеркивает, что TypeScript не меняет функционал приложения, но радикально улучшает читаемость кода и упрощает поиск багов на этапе разработки .