Хотите заказать веб-сайт? Связаться с нами

Рабочий процесс проверки типов в TypeScript

Если каждый раз перезапускать компилятор TypeScript вручную и ждать, пока сгенерируются JavaScript-файлы, разработка быстро превращается в рутину. К счастью, tsc умеет проверять типы отдельно от сборки и делать это в фоновом режиме при каждом сохранении файла. В этом уроке разберём, как встроить проверку типов в повседневный процесс разработки, не жертвуя скоростью и удобством.

Рабочий процесс проверки типов в TypeScript

Флаг noEmit проверка типов без генерации файлов

Компилятор tsc по умолчанию делает две вещи одновременно: проверяет типы и генерирует JavaScript-файлы на основе исходного кода. Но иногда нужен только первый шаг — например, если сборкой уже занимается другой инструмент вроде Vite, esbuild или Babel, а TypeScript используется исключительно для контроля типов.

Именно для этого случая существует флаг --noEmit. Он запускает полноценную проверку типов по всем файлам проекта, но не создаёт ни одного выходного файла:

tsc --noEmit

Если флаг уже прописан в tsconfig.json, отдельно указывать его в команде не нужно:

{
  "compilerOptions": {
    "noEmit": true,
    "strict": true
  }
}

Такой подход удобен, когда сборкой JavaScript-файлов занимается отдельный бандлер, а tsc используется только как инструмент проверки типов, не пересекающийся по задачам с остальным инструментарием проекта.

Добавьте отдельный npm-скрипт "type-check": "tsc --noEmit" в package.json — так проверку типов можно будет запускать одной командой, не запоминая флаги компилятора каждый раз заново.

Режим watch автоматическая проверка при сохранении

Постоянно запускать tsc вручную после каждого изменения кода неудобно. Для автоматизации этого процесса существует флаг --watch (сокращённо -w). В этом режиме компилятор запускается один раз, а затем следит за изменениями файлов и автоматически перекомпилирует проект при каждом сохранении:

tsc --watch

Флаги можно комбинировать. Например, связка --noEmit и --watch запускает постоянную проверку типов в фоне без создания JavaScript-файлов — идеальный вариант, когда сборкой занимается отдельный инструмент, а разработчику важно сразу видеть ошибки типов прямо во время работы:

tsc --noEmit --watch

Такую команду удобно держать запущенной в отдельном терминале или во вкладке редактора. Как только вы сохраняете файл, компилятор почти мгновенно сообщает об ошибках типов, а сообщения появляются прямо там же, без переключения контекста между окнами.

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

На больших монорепозиториях эта проблема становится особенно заметной: разработчики могут ждать по несколько секунд после каждого сохранения, что сбивает рабочий ритм. Если вы столкнулись с такой ситуацией, стоит проверить, не разрастается ли зона проверки без необходимости — например, из-за слишком широких путей include в tsconfig.json или отсутствия разделения проекта на более мелкие модули с собственными конфигурациями.

Встраивание проверки типов в рабочий процесс разработки

Проверка типов приносит пользу только тогда, когда она действительно выполняется на каждом этапе разработки, а не запускается разработчиком время от времени по желанию. Есть несколько способов встроить её в привычный рабочий процесс так, чтобы ошибки типов невозможно было случайно пропустить.

npm скрипты для проверки типов

Самый простой способ — добавить отдельную команду в раздел scripts файла package.json:

{
  "scripts": {
    "type-check": "tsc --noEmit",
    "type-check:watch": "tsc --noEmit --watch"
  }
}

Теперь любой участник команды может запустить проверку одной командой — npm run type-check — не задумываясь о конкретных флагах компилятора.

Проверка перед сборкой и тестами

Ещё один шаг — сделать так, чтобы проверка типов автоматически выполнялась перед более важными задачами, такими как сборка проекта или запуск тестов. Для этого удобно использовать оператор &&, который запустит следующую команду только при успешном завершении предыдущей:

{
  "scripts": {
    "type-check": "tsc --noEmit",
    "build": "npm run type-check && vite build",
    "test": "npm run type-check && vitest run"
  }
}

Если проверка типов завершится с ошибкой, сборка или тесты просто не запустятся. Это исключает ситуацию, когда сломанные типы случайно попадают в собранный код или проходят мимо тестового прогона незамеченными. Такой подход даёт сразу несколько преимуществ:

  1. Ошибки типов невозможно пропустить незамеченными перед сборкой
  2. Все участники команды используют одни и те же команды проверки
  3. Проверка становится частью привычного цикла разработки, а не отдельной задачей

Интеграция с CI

Такой же принцип стоит применять и на уровне CI (continuous integration) — автоматической системы, которая проверяет каждый пуш или пул-реквест. Если проверка типов входит в обязательный набор шагов CI, ни один код с ошибками типов не попадёт в основную ветку репозитория:

steps:
  - run: npm ci
  - run: npm run type-check
  - run: npm run build
  - run: npm test

Чтобы было проще ориентироваться, в каких ситуациях какая команда полезнее, соберём основные варианты в таблицу.

Команда Когда использовать
tsc --noEmit Разовая проверка типов без создания JavaScript-файлов, например перед коммитом или сборкой
tsc --watch Автоматическая пересборка проекта при каждом сохранении файла
tsc --noEmit --watch Проверка типов в реальном времени во время разработки, если сборкой занимается отдельный инструмент

Если проверка типов на больших проектах в режиме --watch заметно тормозит, попробуйте включить в tsconfig.json опцию incremental — компилятор будет сохранять информацию о предыдущей проверке в отдельный файл и переиспользовать её, ускоряя повторные запуски.

Итоги

В этом уроке мы разобрались, как отделить проверку типов от генерации JavaScript-файлов с помощью флага --noEmit, и как автоматизировать эту проверку при каждом сохранении файла с помощью режима --watch. Также мы увидели, что на больших проектах watch-режим может заметно замедлять работу, и рассмотрели несколько способов встроить проверку типов в повседневный рабочий процесс — через npm-скрипты, последовательность команд перед сборкой и тестами, а также через CI.

В следующем уроке мы закрепим эти знания на практике: попробуем самостоятельно объявить недостающие типы в файлах проекта, чтобы устранить ошибки, которые находит компилятор TypeScript.

Теги: