Проблемы совместимости и оптимизация CI перед переходом на TypeScript 7
29 Juli 2026
0
Computing/SoftwareComments (0)
Log in to leave a comment
No posts yet
Log in to leave a comment
No posts yet
Вышел TypeScript 7, чей компилятор был полностью переписан на Go. Новость о том, что скорость проверки типов выросла почти в 12 раз, наверняка заставит команды, управляющие крупными монорепозиториями, задуматься о немедленном переходе. В качестве реального примера: инженерные команды Vanta и VS Code заявили, что сократили время сборки в CI-пайплайнах более чем на 80%.
Однако слепое внедрение может полностью сломать ваш CI. Дело в том, что из-за перехода на нативный бинарник поддержка старых API для статического анализа была отложена на последующие версии. Инструменты вроде @typescript-eslint или ts-morph, которые инспектировали внутренние API через require('typescript'), единоразово перестают работать. Высокая производительность привлекательна, но поломка всей цепочки инструментов — совсем другое дело. Чтобы избежать сбоев в деплое и при этом получить преимущества в скорости, потребуется ряд обходных решений.
Бинарный файл tsc в TypeScript 7.0 полностью блокирует вызовы внутренних модулей Node.js. Пакеты, которые раньше импортировались и использовались в среде JS, моментально выдадут ошибку на этапе сборки. Если просто обновить версию без подготовки, весь CI-пайплайн окажется парализован.
Безопаснее всего установить диагностический скрипт в самом начале пайплайна. Этот подход подразумевает сканирование всех файлов package.json и tsconfig.json в рабочей области для выявления опций и пакетов, отклоняемых в TS 7. Если остаются устаревшие настройки вроде ignoreDeprecations или target: es5, скрипт сразу же выбросит ошибку и остановит процесс.
`javascript
// scripts/check-ts7-compatibility.mjs
import fs from 'node:fs';
import { globSync } from 'glob';
const INCOMPATIBLE_DEPS = [
'ts-morph',
'ts-node',
'@babel/plugin-transform-typescript',
'typescript-eslint',
'@typescript-eslint/parser'
];
const DEPRECATED_TSCONFIG_OPTIONS = ['target:es5', 'moduleResolution:node', 'baseUrl', 'ignoreDeprecations'];
function runDiagnostics() {
console.log('TypeScript 7 호환성 사전 진단 시작...');
let hasError = false;
const packageFiles = globSync('/package.json', { ignore: '/node_modules/' });
for (const file of packageFiles) {
const content = JSON.parse(fs.readFileSync(file, 'utf8'));
const allDeps = { ...content.dependencies, ...content.devDependencies };
for (const dep of INCOMPATIBLE_DEPS) {
if (allDeps[dep]) {
console.warn([의존성 경고] ${file}: '${dep}' 패키지는 TS7 네이티브 API와 호환되지 않습니다.);
hasError = true;
}
}
}
const tsconfigFiles = globSync('/tsconfig*.json', { ignore: '/node_modules/' });
for (const file of tsconfigFiles) {
const rawContent = fs.readFileSync(file, 'utf8');
for (const opt of DEPRECATED_TSCONFIG_OPTIONS) {
if (rawContent.includes(opt)) {
console.error([설정 오류] ${file}: 무효화된 옵션 발견 -> '${opt}');
hasError = true;
}
}
}
if (hasError) process.exit(1);
}
runDiagnostics();
`
Пользовательские AST-трансформеры, зависящие от ts.createProgram() или ts.transform(), также перестанут работать. TypeScript 7.0 не поддерживает внедрение внешних JS-плагинов. Подобную логику необходимо перевести на Rust/C++ биндинги (например, SWC или Babel) или вынести за пределы этапа компиляции.
| Опция компилятора | Поведение в TypeScript 6.0 | Поведение в TypeScript 7.0 | Решение |
|---|---|---|---|
target |
Предупреждение при использовании es5 |
Hard Error (остановка компиляции) | Изменить на es2022 или выше |
moduleResolution |
Разрешено значение node |
Hard Error | Изменить на bundler или node16 |
baseUrl |
Разрешено изолированное использование | Hard Error | Перейти на изолированное использование compilerOptions.paths |
ignoreDeprecations |
Игнорирование предупреждений работает | Опция недействительна и вызывает ошибку | Полностью удалить эту настройку |
strict |
По умолчанию false |
По умолчанию true |
Явно задать значение в tsconfig.json |
TypeScript 7 использует модель потоков Go. В нем появились новые опции: --checkers для параллельной проверки типов и --builders для управления сборкой ссылок на проекты (Project References). Инженерная команда Slack скомбинировала эти опции и сократила время проверки типов с 20 до 4.5 минут. Однако если выделить слишком много потоков без учета количества ядер, накладные расходы на переключение контекста процессора вырастут, и сборка упадет с ошибкой OOM (Out of Memory).
Потоки лучше расчитывать по приведенной ниже формуле в соответствии со спецификацией раннера. Если обозначить выделенное количество ядер виртуальной машины как , общий объем памяти как , резервную память ОС как (), а среднее потребление памяти одним воркером как (), то оптимальное количество потоков для одного проекта рассчитывается следующим образом:
N_{checkers} = minleft( C_{vCPU}, leftlfloor rac{M_{total} - M_{OS}}{M_{worker}} ight floor ight)Сумма всех потоков не должна превышать . Например, для раннера с 8 vCPU / 16GB RAM подходящей настройкой будет --checkers 4 и --builders 2.
`yaml
name: Monorepo Parallel Typecheck
on:
push:
branches: [main]
jobs:
typecheck:
runs-on: ubuntu-latest-8-core
steps:
- name: Checkout Codebase
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install --frozen-lockfile
- name: Purge Legacy TS 6.0 Cache
run: find . -name "*.tsbuildinfo" -not -path "*/node_modules/*" -delete
- name: Execute TS 7 Parallel Check
run: npx tsc --build --checkers 4 --builders 2 --verbose
`
Обратите внимание: инкрементальный движок компиляции TS 7 несовместим по формату с кэш-файлами .tsbuildinfo из TS 6. Если не удалить старый кэш с помощью find . -name "*.tsbuildinfo" -delete перед сборкой, возникнет ошибка сегментации (segmentation fault).
Языковой сервер для редакторов также был переписан на LSP на базе Go. По результатам тестов AWS CodeBuild, время до появления первой ошибки типа при открытии файла в крупном монорепозитории сократилось с 17.5 до 1.3 секунды.
Чтобы унифицировать среду VS Code для членов команды, добавьте следующие настройки в .vscode/settings.json в корне монорепозитория:
`json
{
"typescript.tsdk": "node_modules/typescript/lib",
"js/ts.experimental.useTsgo": true,
"typescript.enablePromptUseWorkspaceTsdk": true,
"typescript.preferences.preferTypeOnlyAutoImports": true,
"files.associations": {
"*.tsbuildinfo": "json"
}
}
`
Иногда возникают конфликты с плагинами для шаблонизаторов вроде Vue или Svelte, из-за чего ломается разбор синтаксиса. В таких случаях можно открыть палитру команд (Ctrl+Shift+P), выбрать TypeScript: Select TypeScript Version... и временно переключиться обратно на старый движок TS 6.0.
Если в вашем проекте используются устаревшие пакеты и вы не можете сразу обновить ESLint до среды TS 7, можно использовать обходной путь с конфигурацией Dual Engine (двойной движок). В этой схеме инструменты статического анализа подключаются к API TS 6, а непосредственно проверка типов и сборка перекладываются на нативный бинарник TS 7.
Установите оба компилятора одновременно, задав алиасы пакетов в package.json:
`json
{
"name": "monorepo-root",
"private": true,
"devDependencies": {
"typescript": "npm:@typescript/typescript6@^6.0.2",
"@typescript/native": "npm:typescript@^7.0.2",
"eslint": "^9.0.0",
"typescript-eslint": "^8.0.0"
},
"scripts": {
"typecheck": "ts-native --build",
"typecheck:legacy": "tsc6 --noEmit",
"lint": "eslint ."
}
}
`
В таком состоянии безопасно подключить к CI скрипт теневой сборки (Shadow Build). Он позволяет сравнить результаты диагностики старого TS 6 и нового TS 7 через diff, чтобы отследить изменения в выводе типов для шаблонных литералов или условных типов.
`bash
#!/usr/bin/env bash
set -e
echo "=== 1. 기존 TS 6.0 컴파일러 진단 출력 생성 ==="
npx tsc6 --noEmit --pretty false > ./ts6-baseline.log 2>&1 || true
echo "=== 2. 신규 TS 7.0 네이티브 컴파일러 진단 출력 생성 ==="
npx --package @typescript/native tsc --noEmit --pretty false > ./ts7-output.log 2>&1 || true
echo "=== 3. 진단 결과 Diff 대조 검증 ==="
DIFF_RESULT=$(diff ./ts6-baseline.log ./ts7-output.log || true)
if [ -z "DIFF_RESULT"
exit 0
fi
`
Пока проблемы совместимости цепочки инструментов не разрешены, наиболее реалистичным решением остается разграничение ролей между линтером и проверкой типов. Если предварительно устранить критические опции с помощью скрипта диагностики и настроить потоки под параметры CI-инфраструктуры, вы сможете ощутимо ускорить процессы без риска остановить пайплайн деплоя.