Конфигурация и миграция — Примеры
Пример 1 — Проект, где аннотации только украшение
Компилятор запускается с выключенной строгой проверкой, и поле, допускающее null, падает в продакшене уже месяц. Скажите, что эта конфигурация на самом деле проверяет, затем включите проверку и заплатите её цену один раз.
{
"compilerOptions": {
"strict": false,
"target": "ES2017"
}
}
const city = order.customer.address.city; // address может быть undefined; ошибки нет
Решение
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"noEmit": true
},
"include": ["src/**/*.ts"]
}
const city = order.customer.address.city;
~~~~~~~
error TS18048: 'order.customer.address' is possibly 'undefined'.
С выключенным strict аннотации описывают замысел, и ничто его не проверяет, поэтому null и undefined проскакивают мимо всех проверок, а ошибки во время выполнения остаются на прежних местах. Включение превращает каждую из них в ошибку на строке, которая её вызвала, поэтому этот параметр стоит включать раньше остальных, а noEmit для фронтенд-проекта тоже обычно верен: код компилирует сборщик, а задача компилятора — только проверять его, чего он не сделает в конвейере, пока там не запущена соответствующая команда.
Пример 2 — Миграция, живущая три недели
Команда переводит весь репозиторий в одной ветке: конфликты накапливаются, работа останавливается, и ветку бросают. Скажите, почему подход провалился, затем переводите так, чтобы сборка оставалась зелёной.
{
"compilerOptions": { "strict": true, "allowJs": false },
"include": ["src/**/*"] // все файлы сразу, все ошибки сразу
}
Решение
{
"compilerOptions": { "strict": true, "allowJs": true, "checkJs": false, "noEmit": true },
"include": ["src/api/**/*.ts", "src/models/**/*.ts"]
}
{ "scripts": { "typecheck": "tsc --noEmit", "check": "npm run typecheck && npm run test" } }
Перевод всего репозитория нельзя ни отревьюить, ни влить в основную ветку, поэтому он никогда и не доводится до конца; растущий список include переводит модуль за модулем, пока нетронутый JavaScript продолжает компилироваться. Начинать с общих границ — клиентов API и моделей данных — выгодно дважды, потому что их типы распространяются наружу и удешевляют перевод оставшихся файлов. allowJs без checkJs даёт импортам из нетипизированных файлов разрешаться без проверки их содержимого — это полезный промежуточный шаг, а не компромисс; проверка же должна стоять в конвейере, ведь ошибка, видимая только в редакторе того, кто последним запускал компилятор, — не принуждение.