Тестирование скорости компилятора Go для TypeScript 7 в реальном приложении Next.js
Практическое сравнение времени выполнения команды tsc между TypeScript 6 и 7 в реальном проекте Next.js, включая ошибку несоответствия в CI и рекомендации по обновлению.
Те же 412 файлов, проверены дважды под управлением двух разных версий компилятора. При использовании TypeScript 6 проверка заняла 3,8 секунды. При использовании TypeScript 7 — 0,41 секунды. Функционально инструмент проверки типов остается тем же.
Публикуемые Microsoft показатели говорят о ускорении в 8–12 раз при работе с VS Code. Однако важным здесь является результат, который показывает команда tsc --extendedDiagnostics для конкретного репозитория. CI-задача, которая раньше тормозила из-за неудачного шага генерации Prisma, не становится в десять раз быстрее только потому, что ускорилась проверка типов; быстрее становится только этот этап. Все последующие этапы в пайплайне остаются такими же медленными, как и раньше.
Откройте терминал.
Пропустите команду next dev. Перейдите сразу к самому инструменту проверки и запустите его из корня приложения:
pnpm exec tsc --noEmit --extendedDiagnostics
Обратите внимание на значение Check time, которое оно выводит. Эта единственная строка является единственным показателем, который стоит отслеживать здесь до самого конца.
Microsoft выпустила TypeScript 7.0 8 июля 2026 года. Сама система типов не изменилась, а бинарник компилятора по-прежнему называется tsc, однако внутренне теперь это порт компилятора на язык Go. В таблице из объявления версии 1.0 показано, что время проверки в VS Code сократилось с 125,7 секунд до 10,6 секунд. Это число относится к собственному кодовому базису Microsoft, а не к типичному проекту Next.js.
На самом деле полезно указать эквивалентное значение для небольшого приложения Next.js с четырьмя маршрутами, уже прошедшего тестирование по всем остальным критериям, а также дополнительное значение: сколько времени занимает команда next build при использовании нового инструмента проверки. Не менее важно задокументировать типы ошибок, которые возникают, когда автоматизированные системы принимают за одно и то же понятия «более высокая скорость» и «иное поведение».
Послеполуденная система CI солгала насчет ошибки типов
Представьте команду, которая во вторник обновила зависимость typescript до версии 7 в приложении для счетоводства, поскольку в одной статье обещали ускорение в 10 раз. Система CI значительно быстрее показала зеленый статус. Вдохновленные этим, рецензенты одобрили и объединили в код базовый инструмент для работы с идентификаторами бренда, который, как оказалось, не выполнял проверку типов на локальном компьютере одного из членов команды.
Помощник собирался без проблем на CI только потому, что там версия typescript 6 все еще загружалась через зависимость из корневого рабочего пространства. На локальном компьютере же была установлена версия 7 напрямую. Сама система типов не изменилась — в этом и заключается суть утверждения Microsoft, — но файл tsconfig на CI привязывал typescript к псевдониму пакета @typescript/typescript6, оставшемуся от настройки, добавленной во время пробного периода и так и не удаленной.
Поэтому настоящей проблемой было не то, что TypeScript 7 ведет себя иначе. Проблемой были два отдельных бинарника компилятора, несогласованность файлов lockfile, а также сообщение в Slack с утверждением, что «7 уже есть», хотя на самом деле его не было, по крайней мере, не везде.
Вот как это выглядело на практике: pull request с названием «Удалить преобразования as InvoiceId, 7 — строже». На самом деле TypeScript 7 здесь не был более строгим. В том же коммите также был включён флаг компилятора erasableSyntaxOnly, что представляет собой совершенно отдельное изменение политики и будет обсуждаться позже. Сочетание чистого улучшения производительности с изменением поведенческой политики — именно так возникают подобные мифы.
Решение заключается в разделении такого коммита на две части: отдельное повышение версии и отдельное изменение политики. Только тогда измерения времени имеют какой-либо смысл.
Фраза, которую на самом деле опубликовала Microsoft
В официальном объявлении о выходе TypeScript 7.0 от 8 июля 2026 года Дэниел Розенвассер описал эту версию как обеспечивающую выполнение нативного кода, многопоточную обработку с использованием общей памяти, а также ряд оптимизаций, которые в среднем увеличивают скорость работы на 8–12 раз при полной компиляции.
Самой часто игнорируемой частью этого объявления является упоминание о том, что система типов остается неизменной.
Согласно объявлению, новая реализация на основе Go была перенята из существующей через тщательный процесс портирования, а не создана заново; её поведение при проверке типов структурно соответствует TypeScript 6.0.
В этом обновлении нет никакой новой синтаксиса. Изменилась лишь скорость выполнения для той же основной логики. Если после повышения версии появляются ошибки типов, это не является ожидаемым поведением — это баг, который стоит задокументировать.
В Next.js 16.3 была добавлена документация, указывающая на то, что команда next build будет использовать TypeScript 7 для проверки типов, если в проекте установлен TypeScript 7 в качестве прямой зависимости. Это предоставляет ещё один способ измерения времени выполнения помимо отдельного запуска tsc.
Два таймера, которые я использовал
По всему тестовому приложению использовались одинаковые настройки: Next.js 16.3, React 19, четыре маршрута, таблица счетов. Для этой сессии флаг компилятора был выключен, чтобы цифры не смешивались.
Первый таймер: tsc --noEmit --extendedDiagnostics. Второй таймер: next build; при этом отслеживалась строка с информацией о проверке типов в выводе.
Я добавил TypeScript 7 в проект в качестве зависимости.
pnpm add -D typescript@7
Экзекутируемый файл по-прежнему называется tsc. Во время фазы предварительного просмотра пакет назывался @typescript/native-preview, а его бинарник — tsgo. Такое название было отменено с выходом стабильной версии. Если вы наткнетесь на гист или тред, в которых всё ещё упоминается tsgo, это относится к периоду предварительного просмотра, а не к текущему инструменту.
Чтобы обе основные версии могли сосуществовать на диске, Microsoft выпустила вспомогательный пакет @typescript/typescript6. Он предоставляет бинарник tsc6, что позволяет обычной команде tsc использовать версию 7, не отказываясь от команд и инструментов, которые всё ещё зависят от версии 6.
pnpm add -D @typescript/typescript6
Далее для обеих версий используется один и тот же файл tsconfig.json:
pnpm exec tsc6 --noEmit --extendedDiagnostics
pnpm exec tsc --noEmit --extendedDiagnostics
Те же исходные файлы. То же значение параметра strict. Те же пути-алиасы, которые сгенерировал Next.js при создании проекта с помощью команды create-next-app.
Каждая команда выполнялась три раза, причем первый результат игнорировался, поскольку кэш файловой системы не отражает реальные условия первой проверки.
Как выглядели цифры в этом кодовом базисе
В тестовом приложении четыре маршрута и примерно 80 файлов на TypeScript, принадлежащих самому проекту, плюс файлы, автоматически генерируемые Next.js.
При использовании TypeScript 6.0 через команду tsc6, при этом брались значения из двух оставшихся результатов:
- Количество проверенных файлов: 412
- Время проверки: 3,82 секунды
- Общее время: 4,25 секунды
При использовании TypeScript 7.0 через команду tsc при идентичной конфигурации:
- Количество проверенных файлов: 412
- Время проверки: 0,41 секунды
Это означает примерно в 9 раз меньше времени на проверку типов. Не в 12 раз, и это далеко не тот резкий сокращение с 125 секунд до 10 секунд, о котором иногда говорят в случае с VS Code. Это просто результат работы данного конкретного репозитория.
Если посмотреть на этап проверки типов внутри next build:
- В версии 6: 5.1 секунды
- В версии 7: 1.4 секунды
Все остальные этапы в next build — сборка и генерация статических файлов для четырех маршрутов — остались примерно на том же уровне. Если ваша CI-пайплайн сначала выполняет проверку форматирования, затем проверку типов, потом сборку и, наконец, тесты конца-конца, то время на проверку типов заметно сокращается, но этап тестов конца-конца не дает никаких преимуществ.
Второй проект, содержащий множество схем Zod и примерно 300 файлов с логикой валидации и обработчиками, показал еще более значительное сокращение времени:
- Время проверки версии 6: 11,4 секунды
- Время проверки версии 7: 1,3 секунды
Код с большим количеством типов, по-видимому, приводит к более значительному ускорению. Небольшой маркетинговый сайт с десятком файлов не покажет ускорения в 10 раз, просто потому что у инструмента по проверке практически нет материала для анализа.
Ошибка, возникшая после обновления
Это было не изменение в поведении проверки типов — это была проблема с инструментарием.
eslint-plugin-react-hooks по-прежнему запускал typescript через настройку parserOptions.project. Это работало нормально в версии 7, но сломалось во время предварительных тестов tsgo ранее. Устаревший блок parserOptions по-прежнему указывал на отдельный файл tsconfig.eslint.json, в котором было установлено "compilerOptions": { "strict": false } для того, чтобы старые тесты не выдавали ошибок.
CI использовал эту упрощённую конфигурацию для проверки кода, в то время как tsc использовал реальную проектную конфигурацию. Два разных источника информации. В результате внутри утилиты для тестирования осталась незамеченная проблема с настройкой noImplicitAny, которую не мог обнаружить инструмент проверки кода. Как только версия 7 сделала запуск tsc достаточно быстрым для постоянного использования, я добавил параметр tsc --noEmit непосредственно в проверки pull-request и полностью удалил упрощённую конфигурацию tsconfig, предназначенную только для ESLint.
{
"scripts": {
"typecheck": "tsc --noEmit",
"lint": "biome check .",
"ci": "pnpm typecheck && pnpm lint && pnpm test && pnpm build"
}
}
Фактическое решение было довольно простым. Ходили слухи, что «версия 7 испортила наши типы». Это не так — проблему вызывала дублирующаяся конфигурация.
Проверка того, что на самом деле запущено на вашем устройстве
Прежде чем верить каким-либо цифрам, убедитесь, какой именно бинарник выполняет работу.
pnpm exec tsc -v
В результатах вы ищете Version 7.x. Если там всё ещё указано 5 или 6, это означает, что ваша рабочая среда использует устаревшую копию из какого-то источника. В monorepo pnpm команда which приведёт вас не туда, в то время как pnpm exec — да.
Запустите диагностику три раза подряд и проигнорируйте результат первого запуска.
pnpm exec tsc --noEmit --extendedDiagnostics
В этих результатах стоит обратить внимание на количество обработанных файлов, долю кода библиотек от общего объёма, долю типовых определений, долю собственного исходного кода, а также на время выполнения проверки и общее время работы.
Теперь установите версию 6 рядом с версией 7 и настройте её на обработку тех же файлов.
pnpm add -D @typescript/typescript6
pnpm exec tsc6 --noEmit --extendedDiagnostics
Если продолжительность проверки не снижается на значимое количество единиц в кодбазе, содержащей сотни файлов, значит либо вы на самом деле не используете версию 7, либо ваш образец слишком мал — дюжина файлов ничего не покажут.
Также стоит выполнить next build дважды, по одному разу для каждого бинарника, и записывать только строку с проверкой типов при каждом запуске. Не следует объединять всю продолжительность сборки в один отчет о скорости TypeScript — Turbopack — это отдельная система, выполняющая свою работу.
Если вы столкнулись с ошибкой типа, которая появляется при использовании версии 7, но отсутствует при использовании версии 6 при идентичном файле tsconfig, сообщите об этом. Это выходит за рамки того, о чем здесь идет речь. Сама Microsoft утверждает, что логика проверки структурно не изменилась, поэтому подобное расхождение является багом, а не чем-то, что следует считать ожидаемыми издержками миграции.
Откуда на самом деле появилась скорость
Положительный эффект проявляется непосредственно в самом проверщике. Работа с синтаксисом и привязкой также ускорилась, но именно время выполнения проверки — это показатель, который отображается в логах CI и который действительно ощущается пользователями.
Отзывчивость редактора — это уже другая история: здесь речь идет о сервисе обработки языка, а не о самостоятельном компиляторе. В таблице счетов действия навигации, такие как переход к определению, субъективно казались более быстрыми. Время нажатия клавиш не фиксировалось, поэтому здесь нет таблицы с показателями в миллисекундах.
next dev и его цикл быстрого обновления не стали значительно быстрее благодаря этому изменению, поскольку быстрое обновление изначально никогда не блокировалось во время полного запуска tsc.
Наибольшая польза проявляется при использовании агентов или автоматизированных циклов, которые запускают команду tsc --noEmit после обработки каждого файла. Теперь цикл выполняется достаточно быстро, поэтому пропуск проверки уже не кажется привлекательной ускоренной альтернативой. В этом и заключается настоящая, хоть и не объявляемая публично, выгода. Тот же агент, который по-прежнему использует обычные перечисления вместо объектов as const, теперь быстрее получает об этом уведомление.
Расчет реальных затрат
Установка: одно увеличение количества зависимостей, плюс удаление ненужного скрипта tsgo.
Влияние на CI: в основном приложении время выполнения шага проверки типов сократилось с 3,8 секунд до 0,4 секунды; в рабочей структуре — с 11,4 секунд до 1,3 секунды. Остальные восемь минут и более процесса обработки остались без изменений.
Последствия слухов: один из pull request’ов возложил вину за регрессию на версию 7, хотя на самом деле она была вызвана изменением флагов, включённым в тот же коммит. Сохраняйте эти коммиты отдельно.
Опыт работы средством редактирования: приятное улучшение, но не настолько значительное, чтобы его нужно было количественно указывать в комментариях.
Номенклатура: теперь tsc означает версию 7, а tsc6 — её альтернативу. Если оба бинарных файла находятся в вашем PATH, чётко опишите это в README, чтобы позже никто не запутался.
Стоит ли обновиться до версии 7 или остаться на 6?
Переходите на версию 7. Поведение проверки типов остаётся прежним — используется тот же движок, только работает быстрее; кроме того, не требуется изучать новую синтаксис.
Оставайтесь на версии 6 только в том случае, если существует конкретный плагин, название которого вы знаете, и он ещё не получил поддержку версии 7. Впишите название этого плагина напрямую в параметр версии. Фраза «Жду стабилизации» сама по себе не является допустимой причиной.
Не объединяйте обновление до версии 7 с изменением параметра erasableSyntaxOnly в одном и том же запросе на пул-реквест — если что-то сломается, вы не сможете определить, какое именно изменение стало причиной.
Также не удаляйте команду tsc --noEmit из вашей CI-пайплайны только потому, что версия 7 делает её более быстрой. Быстродействие — это причина сохранения этого параметра, а не причина его удаления.
Честные ограничения этого сравнения
Сокращение времени с 3,82 секунд до 0,41 секунды касается именно этого приложения с четырьмя маршрутами. Сокращение времени с 11,4 секунд до 1,3 секунды было достигнуто в отдельной базе кода, ориентированной на рабочие процессы. Улучшение в 8–12 раз, о котором говорит Microsoft, относится к полным сборкам в репозиториях размером с VS Code. Здесь никто не пересобирал VS Code.
Фраза «структурно идентичны», датированная 8 июля 2026 года, взята непосредственно из собственного объявления Microsoft. Если ошибки, которые сообщает ваш проект, действительно меняются после обновления, рассматривайте это как дефект, который необходимо задокументировать, а не как какой-то странный побочный эффект, который можно игнорировать.
Отсюда невозможно проверить процесс поднятия зависимостей. Если команда pnpm exec tsc -v показывает одну основную версию локально, в то время как логи CI отображают другую, это означает, что вы еще не проверили версию TypeScript 7 — на самом деле речь идет о проблеме с разрешением пути, маскирующейся под сравнение версий.
Запустите tsc6 и tsc по три раза каждый. Запишите время проверки и количество файлов после каждого запуска. Эти четыре числа составляют первоначальный набор данных, который можно предоставить для получения отзывов по вашей конкретной настройке.
Минимальная схема для папки scratch
Если вы пока не хотите менять свое реальное приложение, вот самая минимальная пара установок, которая всё равно демонстрирует проблему с поднятием переменных.
mkdir ts7-lab && cd ts7-lab
pnpm init
pnpm add -D typescript@7 @typescript/typescript6
echo '{ "compilerOptions": { "strict": true, "noEmit": true } }' > tsconfig.json
echo 'export type InvoiceId = string; export const n: InvoiceId = "inv_1";' > index.ts
pnpm exec tsc -v
pnpm exec tsc6 -v
pnpm exec tsc --extendedDiagnostics
pnpm exec tsc6 --extendedDiagnostics
Запишите строки версий и времена проверки для обоих вариантов. Затем добавьте пакет рабочей среды, который по-прежнему указывает typescript@6 как зависимость, и посмотрите, что выводит команда pnpm exec tsc -v из корня репозитория. Именно такое несоответствие может стать сюрпризом в процессе автоматизированных тестов.
В проекте счетов-фактур ещё одним важным моментом для записи является то, выводилась ли в результатах next build строка Finished TypeScript из версии 7. Если такая строка никогда не появляется, значит Next.js использует отдельный проверщик типов, отличный от того, который запускается скриптом typecheck. Необходимо синхронизировать эти два инструмента — именно из-за одновременного использования двух разных проверщиков ранее произошла утечка бага branded-id.
Одинминутная проверка для рецензентов: откройте файл app/invoices/page.tsx, наведите курсор на тип searchParams и подождите появления подсказки. Повторите действие как для версии 6, так и для версии 7. В этой проверке не требуется таймер — главное, чтобы текст подсказки не менялся между версиями. Поведение остается прежним, но используется более быстрый движок обработки.
Если в вашем проекте существует отдельный файл tsconfig.eslint.json с более слабыми настройками, удаляйте его в ту же неделю после обновления. Простой проверщик типов устраняет необходимость в том, чтобы инструмент lint соблюдал другие правила, чем те, что используются при сборке.
Один показатель, который стоит фиксировать с самого начала: запустите команду tsc --noEmit --pretty false 2>&1, а затем пропустите результат через wc -l до и после обновления. Количество ошибок должно совпадать полностью. В приложении для счетов оно было нулем и нулем. В проекте worker-tree — четырьмя и четырьмя; файлы и сообщения были одинаковыми в обоих случаях. Именно это совпадение и является ключом к пониманию процесса миграции. Если количество ошибок не совпадает, прекратите повторять шаблонные фразы и начните сравнивать логи выхода напрямую друг с другом.
Храните оба лог-файла в форматах /tmp/tsc6.txt и /tmp/tsc7.txt в течение примерно недели после каждого обновления. Удалите их, когда ситуация стабилизируется — но не в ту ночь, когда вы фактически выпускаете обновление.
Рекомендации для тех, кто будет продолжать работу с этим кодовым базисом
В шаблоне pull request обязательно укажите результат выполнения команды pnpm exec tsc -v. Если там не указано число 7, значит улучшение производительности на самом деле не было включено в выпуск.
Не сочетайте это обновление с параметрами erasableSyntaxOnly, verbatimModuleSyntax или более полной очисткой настроек tsconfig в одном изменении. Это относится к последующим этапам работы. Данное обновление касается лишь ускорения работи компилятора при выполнении тех же задач.
Продолжайте использовать параметр tsc --noEmit в CI, даже если он теперь практически не требует ресурсов. Именно такая низкая стоимость является аргументом в пользу его сохранения.
Запись сеанса в лаборатории: команды и результаты
В этом разделе описан тот же лабораторный экземпляр с четырьмя маршрутами, который использовался во всей этой серии. Версии, зафиксированные перед началом: Node 24, TypeScript 7, Next 16.3.
Эти инструкции находятся в файле notes/lab.md репозитория, чтобы последующие сессии не зависели от памяти. Их можно скопировать по порядку.
node -v
pnpm exec tsc -v
pnpm exec next --version
Запишите все три номера версий вверху своей записки. Если какая-либо основная версия не совпадает с той, которую, по вашему мнению, вы используете, остановитесь на этом — всё, что будет после, приведет к вводящим в заблуждение результатам более тонким способом.
Далее идет описание маршрутов:
pnpm exec next dev
Посетите /, /invoices, /invoices/1, /settings, затем снова /invoices. Включите опцию «Сохранять журнал» в DevTools. Сделайте скриншот как полей фильтрации, так и строки адреса. Эта пара данных оказывается наиболее полезной для большего количества проверок, чем ожидалось.
Затем запустите проверку типов:
pnpm exec tsc --noEmit --pretty false
echo $?
Код выхода равный нулю не является окончательным результатом — это лишь сигнал к проверке поведения приложения во время выполнения.
Наконец, суть всего этого: выполните команды, уже перечисленные в разделе «Как посмотреть на своем устройстве». Не пропускайте их только потому, что вы уже видели здесь цифры — ваше устройство не является тем, откуда они взялись. Температура окружающей среды, ноутбук на 16 ГБ и любые процессы, выполняемые Chrome на фоне, повлияют на показатели RSS, времени проверки и времени прерывания загрузки гораздо сильнее, чем любое незначительное обновление фреймворка.
Еще одна привычка, которую стоит сохранить: одна строка с указанием «неудачной попытки решения» в записи — одно предложение, например «Попробовал X, но все равно получил Y». Именно такая строка делает запись рабочим отчетом, а не отформатированным презентационным материалом. Полезной дополнительной информацией являются список версий, точная команда, результат ее выполнения и описание неудачной попытки решения. Скриншот панели управления не считается такой информацией.
Связанные материалы
- Компилятор TypeScript на Go и нативная реализация: руководство по миграции — Узнайте, как компилятор TypeScript на основе Go и нативная реализация в Node.js повлияют на кодовые базы React и Next.js, а также что необходимо исправить в вашем tsconfig прямо сейчас.
- Как работает переписывание кода TypeScript 7 на Go: ускорение без изменений в коде — Узнайте, как компилятор TypeScript 7 на основе Go обеспечивает в 8–12 раз более быструю сборку, почему так работает изменение архитектуры и как безопасно обновить существующие проекты.