Сборка и тулчейн
Главный водораздел темы — проверка типов и транспиляция это две разные работы, и современная сборка их разводит. esbuild, SWC и Babel срезают типы пофайлово, без checker: они читают один файл, стирают аннотации и эмитят JavaScript — они никогда не строят программу, не открывают соседние файлы и потому в принципе не могут сообщить об ошибке типа. Отсюда их скорость (в 10–100 раз) и требование семантики isolatedModules. Проверяет типы только tsc (в режиме --noEmit или tsc -b), и он же — единственное, что умеет вывести .d.ts. Практическое следствие: dev-сервер (Vite, Next) типы не проверяет вообще, ошибки всплывают лишь в редакторе и в CI, поэтому tsc --noEmit обязан быть гейтом.
Вторая половина темы — как ускорить саму проверку. TypeScript 7.0 (GA 8 июля 2026, Go-нативный компилятор; в npm latest — 7.0.2) портирует тот же checker на Go: это порт, а не переписывание, и он меняет только задержку, а не систему типов. При этом 7.0 вышел без программного API (нацелен на 7.1), поэтому всё, что грузит компилятор как библиотеку, осталось на TypeScript 6.0 (предыдущая линия, 23 марта 2026). На уровне репозитория скорость дают project references и инкрементальный .tsbuildinfo, а когда проверка всё равно тормозит — её надо не гадать, а измерять счётчиками --extendedDiagnostics и трассой. Разбор по слоям — ниже.
Карта темы
- Тулчейн сборки — почему проверка типов и транспиляция это разные работы, почему
esbuild/SWCне могут найти ошибку типа и зачемtsc --noEmitобязан быть гейтом в CI. - Go-нативный компилятор — что TypeScript 7.0 портирует тот же checker на Go ради скорости, что он не меняет и почему у него пока нет программного API.
- Project references — как
references+compositeпревращают пакет в отдельно собираемую единицу, проверяемую против.d.ts, а не против исходников соседа. - Инкрементальная сборка — что
.tsbuildinfoкеширует, почему правка тела файла дешевле правки его сигнатуры и когда кеш надо выбрасывать. - Конфигурация монорепо —
tsconfig.base.json+extends, чемpathsотличается отworkspacesи почему одна корневая программа не масштабируется. - Линтинг — как
typescript-eslintстроит программу и ловит то, что дляtscне ошибка типов: забытые promise, небезопасныйany, правила идиом. - Диагностика компилятора — как читать вложенную ошибку «не присваивается» снизу вверх и какими флагами узнать, почему файл вообще попал в программу.
- Скорость проверки типов — почему проверка типов взрывается, какие счётчики читать в
--extendedDiagnosticsи как найти виновный тип трассой.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
Считать зелёную сборку esbuild доказательством корректных типов | Транспилятор типы не проверяет вообще — ошибка уедет в прод, пока tsc --noEmit не стоит гейтом |
Принимать isolatedModules за флаг скорости | Это ограничение однофайлового эмита: запрещает const enum между файлами, неоднозначные type-only импорты, export = |
| Ждать от TypeScript 7.0 новых возможностей системы типов | Это порт того же checker на Go — те же программы проходят и падают с теми же диагностиками; меняется только скорость |
| Пересказывать бенчмарк «Go против Rust» | Ни один первоисточник не описывает такого сравнения — это порт, а не переписывание, и Rust никто не отвергал |
Обновлять typescript-eslint/Volar/Angular на TypeScript 7.0 | У 7.0 нет программного API (нацелен на 7.1) — библиотеке нечего вызвать, поэтому они закреплены на 6.0 |
| Считать чистую сборку TypeScript 6.0 доказательством готовности к 7.0 | 6.0 лишь депрецировал es5/AMD/UMD/node10/baseUrl/outFile; 7.0 делает их жёсткими ошибками |
Путать references с paths | paths — только алиас для checker; references строит граф отдельно собираемых проектов с .d.ts на границе |
Забыть composite: true на указанном проекте | tsc -b теряет проверку актуальности — либо ошибка, либо перепроверка всего замыкания вниз по графу |
Ждать, что .tsbuildinfo кеширует эмитированный JavaScript | Он хранит хеши версий входов и граф сигнатур; смена опций или версии компилятора выбрасывает кеш целиком |
| Держать barrel-файл, реэкспортирующий всё | Любая правка сигнатуры расходится через бочку по всему графу зависящих, раздувая веер инвалидации |
Разрешать paths только в tsconfig | Это алиас лишь для checker — бандлер, jest и Node о нём не знают, пока алиас не продублирован в их резолверах |
Включать типо-зависимые правила без parserOptions.project | Правила молча отключаются — линтер работает по синтаксису, и no-floating-promises не срабатывает |
| Читать «Type X is not assignable to type Y» сверху вниз | Цепочка сужается к внутреннему несоответствию — читать надо снизу вверх; ... разворачивает --noErrorTruncation |
| Винить число файлов или диск за медленную проверку | Если парсинг и биндинг близки к нулю, время сидит в проверке — это взрыв инстанцирований, а не ввод-вывод |
Оставлять skipLibCheck: false | Компилятор перепроверяет каждый .d.ts в node_modules — лишняя работа на ровном месте |
| Гадать, какой дженерик тормозит | Снимите --generateTrace и откройте в Perfetto/analyze-trace — счётчик Instantiations назовёт виновника |
Значение для собеседований
Тема отделяет кандидата, который «настраивал сборку по инструкции», от того, кто понимает модель исполнения тулчейна. Первый же вопрос — «чем tsc отличается от esbuild?» — проверяет не знание команд, а понимание того, что транспилятор физически не строит программу и потому не проверяет типы. Второй пласт — точность в фактах TypeScript 7.0: интервьюер слушает, назовёте ли вы версию (а не «новейшую»), отличите ли порт от переписывания и вспомните ли, что у 7.0 ещё нет программного API.
Что обычно проверяют:
- Чем
tscотличается отesbuild/SWCи почемуtsc --noEmitнужен гейтом в CI. - Что портирует TypeScript 7.0 и что он не меняет; почему это порт, а не переписывание на Rust.
- Почему
typescript-eslint, Volar и Angular остались на TypeScript 6.0. - Что дают
project references+compositeи чем они отличаются отpaths. - Что кеширует
.tsbuildinfoи когда он становится несвежим. - Что положить в
tsconfig.base.json, а что — в конфиг пакета. - Что ловит
typescript-eslintсверхtsc. - Как диагностировать медленную проверку типов по
--extendedDiagnosticsи трассе.
Типичный неверный ответ: «TypeScript 7.0 — это новейшая версия, надо просто поставить её везде». Здесь сразу два провала: «новейшая версия» вместо номера и вера в прямую замену. На деле назовите версию (7.0 GA 8 июля 2026, latest — 7.0.2, 6.0 — предыдущая линия), знайте, что это порт того же checker без программного API, поэтому переехать может CLI (tsc --noEmit), а всё, что грузит компилятор как библиотеку, остаётся на 6.0. Второй классический промах — «раз esbuild собрал, значит типы корректны»: транспилятор типы не смотрит вообще, и без tsc --noEmit в CI ошибка типа уходит незамеченной.