Гид по технологиям

Создание React‑проекта с TypeScript

6 min read Frontend Обновлено 17 Dec 2025
Создание React‑проекта с TypeScript
Создание React‑проекта с TypeScript

Крупный план тёмных клавиш печатной машинки

О чём эта статья

Эта статья шаг за шагом показывает, как создать и настроить React‑проект с TypeScript, как типизировать компоненты, пропсы, state и события. Включены практические примеры, советы при миграции, чек‑листы для разработчиков и альтернативные подходы.

Важно: TypeScript не выполняет код в рантайме — это инструмент статической проверки типов и разработки. Он улучшает качество кода и опыт разработки, но не заменяет тестирование и линтинг.

Почему TypeScript в React полезен

JavaScript — слаботипный язык, и ошибки типов часто обнаруживаются только при исполнении. TypeScript вводит систему типов поверх JavaScript, что помогает:

  • обнаруживать ошибки на этапе компиляции;
  • улучшать автодополнение и навигацию по коду в IDE;
  • формализовать контракты компонентов через типы и интерфейсы.

При этом есть компромисс: иногда требуется писать дополнительный «боилерплейт» при типизации сложных случаев.

Создание React‑проекта с TypeScript

Самый простой способ — создать проект с шаблоном TypeScript через create-react-app:

npx create-react-app app-name --template typescript

Если у вас уже есть приложение на React, можно добавить TypeScript в проект:

npm install --save typescript @types/node @types/react @types/react-dom @types/jest

После установки поменяйте расширения файлов компонентов на .tsx и начните добавлять типы.

Проблема: “React refers to a UMD global, but the current file is a module”

Иногда при переименовании в .tsx вы увидите ошибку о глобальном React. Решения:

  • Явно импортировать React в файле:
import React from "react";
  • Или настроить tsconfig.json и установить jsx в react-jsx (рекомендуется для нового кода):
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "target": "es6",
    "module": "esnext"
  }
}

Полный список опций смотрите в официальной документации TypeScript.

Как писать функциональный компонент в TypeScript

Функциональные компоненты в TypeScript записываются так же, как в JavaScript, но при желании можно добавить аннотацию возвращаемого типа:

export default function Greetings() {
  return (
    
Hello world
); }

С аннотацией возвращаемого типа:

export default function Greetings(): JSX.Element {
  return (
    
Hello world
); }

TypeScript проверит, что компонент возвращает допустимый JSX.Element.

Пропсы компонентов и их типизация

Пропсы можно типизировать прямо в сигнатуре функции или вынести в отдельный тип/интерфейс.

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;
}

Если пропс не передан, TypeScript не будет ругаться.

Состояние (useState) и его типизация

При простых начальных значениях TypeScript может вывести тип автоматически:

const [customerName, setCustomerName] = useState("");

Когда начальное значение отсутствует или может быть null, указывайте тип явно:

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
});

Если состояние может быть null в начале, применяйте объединение с null:

const [profile, setProfile] = useState(null);

События в React и их типы

React экспортирует типы событий, которые помогают корректно типизировать обработчики.

Пример некорректно типизированного компонента (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 (
    
); }

Типизированный пример — вариант с ChangeEvent:

import { ChangeEvent, useState } from 'react';

export default function Login() {
  const [email, setEmail] = useState('');

  const handleChange = (event: ChangeEvent) => {
    setEmail(event.target.value);
  };

  const handleClick = (event: React.MouseEvent) => {
    console.log('Submitted!');
  };

  return (
    
); }

Альтернатива — типизировать сам обработчик через ChangeEventHandler / MouseEventHandler:

import { ChangeEventHandler, MouseEventHandler, useState } from 'react';

const handleChange: ChangeEventHandler = (event) => {
  setEmail(event.currentTarget.value);
};

const handleClick: MouseEventHandler = (event) => {
  console.log('Submitted!');
};

Совет: для больших форм используйте библиотеки, которые уже поддерживают TypeScript (Formik, React Hook Form) и схемы валидации (Zod, Yup).

Когда TypeScript даёт наибольшую пользу и когда он может мешать

Когда стоит использовать TypeScript:

  • крупные проекты с множеством компонентов и командой разработчиков;
  • код, который поддерживается длительное время;
  • важна безопасность API между слоями (компоненты, хранилище, бэкенд).

Когда TypeScript может казаться излишним:

  • маленькие одноразовые скрипты или прототипы;
  • когда дедлайн и обучение команды ещё не завершено;
  • при частых экспериментальных изменениях, где типы часто ломают быстро меняющийся код.

Мини‑методология миграции существующего проекта на TypeScript

  1. Установите зависимости: typescript и @types/* для используемых пакетов.
  2. Создайте tsconfig.json и включите incremental и allowJs: true для плавной миграции.
  3. Переименуйте по одной папке .js → .tsx и исправляйте ошибки типов постепенно.
  4. Добавьте строгие правила постепенно: сначала “noImplicitAny”: false, затем включайте строгие опции.
  5. Интегрируйте линтер и форматер (ESLint с плагином TypeScript, Prettier).
  6. Пишите типы для публичных интерфейсов и пропсов в первую очередь.

Чек‑лист для ролей

Разработчик:

  • Добавил/обновил tsconfig.json.
  • Переименовал файлы и исправил критические ошибки типов.
  • Написал интерфейсы для пропсов и внешних API.
  • Добавил типы для useState и обработчиков событий.

Код‑ревьювер:

  • Проверил корректность интерфейсов и отсутствие any без причины.
  • Убедился, что публичные типы документированы.
  • Оценил влияние изменений на потребителей компонента.

Техлид:

  • Установил стратегию миграции и целевые опции компилятора.
  • Контролирует включение строгих опций поэтапно.
  • Проверяет интеграцию с CI и сборкой.

Snippets и шпаргалка по типам (cheat sheet)

  • Типизация пропсов: type Props = { a: string; b?: number };
  • useState с объектом: const [s, setS] = useState(initial);
  • Обработчик input: (e: ChangeEvent) => void
  • Кнопка: React.MouseEvent
  • Ref на элемент: useRef(null)

Альтернативы TypeScript

  • PropTypes — простая валидация в рантайме (подходит для небольших проектов).
  • Flow — статическая типизация от Facebook (реже используется сейчас).
  • Runtime‑валидация (Zod/Yup) — полезна для схем данных и валидации вне типов.

Модели мышления и эвристики

  • Типизируйте API на границе модулей: пропсы, контексты, публичные функции.
  • Начинайте с поверхностных типов и уточняйте их по мере необходимости.
  • Избегайте подавления ошибок через any — используйте // TODO с задачей на последующую типизацию.

Decision flow (простая диаграмма выбора)

flowchart TD
  A[Проект новый?] -->|Да| B[Использовать шаблон TypeScript]
  A -->|Нет| C[Есть память времени на миграцию?]
  C -->|Да| D[Пошаговая миграция: allowJs -> .tsx -> усиление строгих правил]
  C -->|Нет| E[Оставить JS, добавить типы по мере необходимости или использовать PropTypes]

Когда TypeScript может не помочь (примеры неудач)

  • Ошибки логики (не типовые) TypeScript не поймает — нужны тесты.
  • Некорректные типы внешних API: если бэкенд возвращает неожиданные структуры, статическая типизация без валидации рантайма даст ложное ощущение безопасности.

Краткая памятка по ошибкам и их решениям

  • “JSX element type ‘X’ does not have any construct or call signatures” — проверьте экспорт/импорт компонента и расширение файла.
  • “Property ‘foo’ does not exist on type ‘Bar’” — обновите интерфейс/тип или корректно сприньте преобразование данных.
  • Неправильное использование any — фиксируйте в ревью и заменяйте уточняющими типами.

1‑строчный глоссарий

  • TypeScript — надстройка над JavaScript с системой типов;
  • JSX.Element — тип возвращаемого значения функционального React‑компонента;
  • Generics — обобщённые типы, например useState;
  • Interface / type — способы объявления структур типов;
  • Props — входные данные компонента;
  • useState — хук для локального состояния.

Сводка

TypeScript делает React‑разработку более надёжной и предсказуемой, особенно в средних и крупных проектах. Начните с шаблона при новом проекте или внедряйте поэтапно в существующий код. Комбинация TypeScript, тестов и линтинга даёт наилучший результат по качеству и поддерживаемости кода.

Важно: не забывайте про интеграцию с CI и документацию публичных типов.

Краткое завершение и рекомендации:

  • Для новых проектов используйте create-react-app с –template typescript или Vite + TypeScript.
  • Для существующих проектов мигрируйте по шагам, не включая сразу все строгие опции.
  • Типизируйте границы модулей в первую очередь: пропсы, контексты, API.

Спасибо за чтение. Удачной миграции и безопасной разработки!

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Find My Device в Windows 11 — включение и поиск
Windows

Find My Device в Windows 11 — включение и поиск

Шаблоны автоответа «Вне офиса» и практические советы
Коммуникации

Шаблоны автоответа «Вне офиса» и практические советы

Подпись в Outlook: шаблон и настройка
Почта

Подпись в Outlook: шаблон и настройка

Объединение ячеек в Excel: & и CONCAT
Excel

Объединение ячеек в Excel: & и CONCAT

Как поделиться экраном в Zoom
Видеоконференции

Как поделиться экраном в Zoom

Яркость клавиатуры MacBook Air — как изменить
Руководство

Яркость клавиатуры MacBook Air — как изменить