Конфигурация и миграция
Что это такое
Поведением TypeScript управляет файл tsconfig.json: какие файлы проверяются, какие языковые возможности разрешены, насколько строго проверяются типы и какой JavaScript выдаётся на выходе. Миграцией называют добавление такого файла в существующий проект на JavaScript без остановки работы над новыми возможностями.
Почему это важно
Параметры компилятора решают, будет система типов активом или формальностью. Проект с выключенным strict получает подсветку синтаксиса и почти ничего больше, а тот же проект с включённым находит настоящие дефекты в коде, который работает не первый год. На практике сложнее миграция, потому что большую нетипизированную кодовую базу нельзя перевести одним коммитом: проверки нужно вводить постепенно, в таком порядке, который сохраняет сборку зелёной, а команду — незаблокированной; команды, которые этого не планируют, либо оставляют strict выключенным навсегда, либо проводят неделю со сломанной сборкой.
Ключевые идеи
Включайте строгость для нового кода
Важнее всего параметры strict, noUncheckedIndexedAccess и exactOptionalPropertyTypes. Включить их сразу для всего старого проекта часто невозможно, зато включить их для файлов, которые уже типизированы, ничего не стоит и не даёт копиться новому долгу.
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"noEmit": true
},
"include": ["src/**/*.ts"]
}
noEmit обычно верен для фронтенд-проекта: код компилирует сборщик, а задача TypeScript — только проверять его.
skipLibCheck — прагматичный выбор по умолчанию
Он пропускает проверку файлов объявлений зависимостей, которые часто написаны для другой версии компилятора. Изредка он скрывает настоящие проблемы; на практике он убирает много ложных.
Разрешайте и запрещайте JavaScript явно
allowJs позволяет компилятору обрабатывать файлы JavaScript, а checkJs заставляет его проверять их типы. Один только allowJs даёт импортам из нетипизированных файлов разрешаться без проверки их содержимого — полезный промежуточный шаг во время миграции.
Мигрируйте, расширяя границу
Практический путь — растущий список include: добавляйте файлы TypeScript, держите их строгими и позволяйте им импортировать JavaScript. Сначала дайте явные типы общим границам — клиентам API, моделям данных, — потому что эти типы распространяются наружу и удешевляют перевод остального.
Проверяйте типы в CI, а не только в редакторе
Ошибка, которая видна только на машине того, кто последним запускал компилятор, — это не принуждение. Аннотации остаются правдивыми только благодаря шагу tsc --noEmit в конвейере.
Практика
Включите один строгий параметр и разберите последствия
Возьмите существующий проект, включите один строгий параметр и исправьте все ошибки, которые он породит, не добавляя any.
Готово, когда: компилятор сообщает ноль ошибок, в диффе нет новых any, и вы можете назвать один настоящий дефект, который параметр выявил.
Переведите один модуль и закрепите границу
Переведите один модуль из файла JavaScript на TypeScript, типизируйте его публичные экспорты и добавьте в сборку шаг tsc --noEmit.
Готово, когда: модуль чисто импортируется из оставшегося JavaScript, его экспортируемые типы используются в месте вызова без приведений, а сборка падает, если кто-то их нарушит.
Частые ошибки
strictвыключен бессрочно — аннотации типов описывают замысел, но ничто его не проверяет; исправить: включите его для новых каталогов сейчас, а старые переводите следом.- Перевод всего репозитория в одной ветке — ветка живёт неделями, конфликты накапливаются, и работу бросают; исправить: переводите файл за файлом, сохраняя сборку зелёной на всём протяжении.
any, чтобы первая миграция скомпилировалась — код выглядит типизированным, но до него не доходит ни одна проверка; исправить: используйтеunknownна настоящих границах и сужайте в месте применения.- Проверка типов только в редакторе — нетипизированный файл попадает в
main, и сборка ломается у следующего человека; исправить: запускайтеtsc --noEmitв CI. targetниже, чем нужно вашим браузерам — вывод остаётся многословным, и старый синтаксис сохраняется без надобности; исправить: задайтеtargetпо реальной матрице поддержки.
Что читать дальше
- Обобщения (02-frontend/19-typescript/03-generics) — утилитарные типы и вывод — инструменты, к которым вы тянетесь, исправляя ошибки строгого режима.
- Управление пакетами (npm) (02-frontend/04-package-management-npm) — откуда берутся компилятор и его пакеты типов и как фиксируются версии.
- CI/CD (06-cloud-devops/08-ci-cd) — место, где должна стоять проверка
tsc --noEmit.