Почему порт TypeScript 7 на Go сломал инструменты проверки кода и средства разработки фреймворков.
Объясняет, почему более быстрый компилятор TypeScript 7 на основе Go поставляется с несовместимым API, что нарушает работу инструментов проверки кода, процесс установки и обновления фреймворков Vue/Svelte во всей экосистеме.
Компилятор выпущен. API, который должен был поставляться вместе с ним, — нет.
Microsoft выпустила TypeScript 7.0 8 июля 2026 года, и заголовок практически сам собой сложился: в десять раз быстрее. Компилятор перешел с JavaScript на Go, работает в нескольких потоках и обрабатывает кодовые базы, которые раньше требовали двух минут полной обработки, теперь же завершает работу ещё до того, как вы успеваете переключиться на другое окно. Почти каждый новостной бюллетень, освещающий этот релиз, начинался с той же диаграммы тестовых показателей.
Затем разработчики действительно выполнили команду npm install.
Многие из них получили быструю двоичную версию, работающую на сломанной среде разработки. Причем проблема была весьма серьезной: инструменты проверки кода падали даже при простом чтении свойства. Менеджеры пакетов отклоняли установку из-за несоответствия диапазонов зависимостей. Проекты на Vue и Svelte вообще не могли обновиться. Через месяц ситуация почти не изменилась, и исправления пока не запланированы ни для одной версии с установленной датой выпуска.
Именно эта часть истории осталась незамеченной, хотя именно она определяет, стоит ли вам сейчас проводить это обновление.
Цифры, которые цитируют все
Сначала следует отдать должное авторам — улучшения производительности — это не просто маркетинговые выдумки. Microsoft опубликовала собственные цифры тестов в объявлении о выпуске, и они достаточно подробны для проверки.
Команда сообщает о ускорении в диапазоне от 8 до 12 раз при полной сборке, причем использование памяти даже снизилось вместо того, чтобы расти, что противоположно обычному компромиссу. Slack сообщил Microsoft, что время проверки типов в их CI-пайплайне сократилось с примерно семи с половиной минут до чуть более одной минуты, а скорость загрузки редактора с почти непригодного уровня для таких масштабов стала достаточной для загрузки в течение нескольких секунд. Canva сообщил, что время появления первой ошибки в редакторе сократилось с примерно 58 секунд до менее чем 5.
Это реальные инженерные достижения, результат годовых усилий. Ничто из того, что будет сказано далее, не может этому противоречить.
Это была портированная версия, а не полная переработка
Вот технические детали, которые большинство публикаций проигнорировало, и именно они объясняют всё остальное.
TypeScript 7 представляет собой порт, а не полную переработку с нуля. Команда переводила существующие файлы компилятора по одному из TypeScript на Go, намеренно сохраняя первоначальную структуру и логику, чтобы поведение проверки типов оставалось идентичным. Ожидается, что всё, что компилировалось без проблем в версии 6.0, будет компилироваться так же в версии 7.0. Именно так Microsoft смогла выпустить компилятор такого масштаба без большого количества регрессий в поведении, и это свидетельствует о настоящей дисциплине при выполнении процесса портирования.
Но компилятор на самом деле представляет собой два отдельных продукта, имеющих одно название. Есть бинарный файл, который вы запускаете — tsc. И есть библиотека, которую другие инструменты используют в качестве зависимости. Инструменты проверки синтаксиса, преобразователи тестов, модификаторы кода на основе дерева синтаксического анализа и проверщики шаблонов не обращаются к tsc и не анализируют текст, который он выводит. Вместо этого они импортируют TypeScript напрямую, прослеживают структуру синтаксического дерева с его помощью и получают информацию о типах непосредственно из проверщика.
Порт верной манерой перенес первый продукт. Второй же вообще не был перенесен.
Сам компилятор остался нетронутым. API, от которого зависят все окружающие инструменты, не был перенесен вместе с ним.
Строка, спрятанная почти в конце записей об обновлении
Чтобы быть справедливым к Microsoft, это не скрывалось. Если прочитать объявление о версии 7.0 примерно на две трети его длины, в разделе, посвящённом тому, как запускать 7.0 вместе с 6.0, там есть предложение, о котором весь экосистема обсуждала весь июль: TypeScript 7.0 поставляется без API.
Это значительный пробел. Microsoft утверждает, что она разрабатывает новый API и планирует сделать его доступным в версии 7.1. По словам команды, теперь, когда работа по портированию завершена, они снова сосредотачиваются на добавлении новых функций.
Заявленный темп — выпуск новой версии каждые три–четыре месяца. Если этот график соблюдаться, версия 7.1 появится примерно в октябре. Это всё, что известно на данный момент — ещё нет подтверждённой даты, когда сам заменяющий API будет готов.
Прочитайте объявление с верха до низа, и схема станет ясной. Сначала приводится таблица, показывающая насколько быстрее работает версия 7.0. Затем следуют восторженные отзывы крупных компаний. Только после этого Microsoft упоминает, почти мимоходом, что значительная часть инструментальной экосистемы пока вообще не может работать с этой версией.
Такой порядок был преднамеренным редакционным выбором, а не попыткой кого-либо ввести в заблуждение. Но именно поэтому многие команды обнаружили проблему с API из журнала ошибок в своем терминале, а не непосредственно из самого объявления.
Проблема 12518
Самым полезным материалом, появившимся в неделю запуска, не был тест-результат. Это был отчет об ошибках.
В день, когда новый компилятор стал общедоступным, кто-то, обновлявший проект Vite с React с версии 6.0.3 до 7.0.2, открыл задачу номер 12518 против typescript-eslint вместе с примером её возникновения. В ней были описаны два отдельных сбоя.
Первый заключался в том, что команда npm ci совсем отказывалась выполнять установку, поскольку метаданные пакета typescript-eslint задавали диапазон версий взаимозависимостей, из которого версия 7.0.2 выходила. Второй сбой возникал у тех, кто всё же пытался выполнить установку: ESLint ломался в компоненте typescript-estree во время сборки программы, так как код пытался обратиться к свойству API компилятора, которого уже не существовало в этой версии.
Администраторы проекта закрыли эту задачу. Не потому, что им было всё равно, а потому, что не было ничего, что можно было бы сделать.
Если прочитать это по отдельности, может показаться, что речь идет о пренебрежительном отношении. Но это не так. У разработчиков typescript-eslint нет возможности самостоятельно исправить эту проблему — компонент, необходимый для ее решения, еще не выпущен. Закрытие задачи было просто честным отражением фактов: настоящая работа должна быть выполнена в TypeScript 7.1, а не внутри инструмента проверки кода. Это означает, что самый популярный инструмент TypeScript в экосистеме в настоящее время бессилен что-либо сделать по поводу собственной совместимости.
На следующий день основная команда ESLint открыла соответствующую задачу, подтвердила намерение ее решить, но также оказалась в той же ситуации из-за отсутствия необходимого компонента. Разработчики инструментов для Vue находятся в аналогичном положении. Все, кто использует эти инструменты, застряли из-за той же нерелизованной зависимости.
Масштаб влияния
Любой пакет, который импортирует typescript и обращается к его внутренним компонентам, подвержен этой проблеме. Более конкретно:
- typescript-eslint вместе со всеми правилами проверки кода, основанными на анализе типов. Это приводит к явной ошибке либо во время установки, либо сразу при первом запуске — её невозможно не заметить.
- ts-jest и любые трансформаторы, основанные на внутренних вызовах компилятора. В отличие от предыдущего случая, здесь ошибка проявляется более тихо: появляются запутанные сообщения об ошибках трансформации вместо сбоя при установке, что, пожалуй, ещё хуже, поскольку это выглядит как проблема с конфигурацией тестов, а не несоответствие версий.
- ts-morph и любые пользовательские модификаторы кода, созданные на его основе. Эта категория считается самой рискованной. Глубокий анализ типов может происходить незаметно, что приводит к косвенно неверному результату вместо явного сбоя. Тщательно проверьте ситуацию перед тем, как применять что-либо разрушительное к кодовой базе.
ts-loader по-прежнему используют устаревший API. Один из комментаторов объяснил общее настроение: все хотят обновиться, но поскольку большинство проектов работает с webpack и пока нет совместимого API для загрузчиков, все ждут выхода версии 7.1.Внимательно посмотрите на список. Среди них нет ничего узкоспециализированного или экзотического — это стандартный набор инструментов типичной команды фронт-энда сегодня.
Сам компилятор стабилен. Однако экосистема вокруг него — нет. Это два разных состояния релиза, которые делят один и тот же номер версии.
Решение Microsoft: установить два компилятора одновременно
Microsoft предвидела такие трудности и создала обходной способ, вместо того чтобы заставлять команды самостоятельно что-то придумывать. Они выпустили @typescript/typescript6 — пакет совместимости, содержащий исполняемый файл tsc6 и восстанавливающий доступ к интерфейсу API версии 6.0. Это позволяет старому и новому компиляторам сосуществовать без конфликтов по именам бинарных файлов.
Этот обходной путь необходим потому, что такие инструменты, как typescript-eslint, разрешают импорт TypeScript по имени пакета через связь типа peer dependency. Поэтому рекомендуемым решением является использование псевдонима npm для перенаправления этого имени.
Полная настройка с двумя компиляторами выглядит следующим образом:
{
"devDependencies": {
"@typescript/native": "npm:typescript@^7.0.2",
"typescript": "npm:@typescript/typescript6@^6.0.2"
}
}
С такой настройкой инструменты проверки кода, преобразователи тестов и модификаторы кода продолжают импортировать typescript как обычно, при этом внутри системы используется версия 6.0. В то же время выполнение команды npx tsc приводит к использованию версии 7.0, что позволяет сохранить преимущества скорости там, где это важно — в редакторе и в процессах CI.
Этот метод действительно работает, и заслуги в этом следует признать: это хорошо спроектированный обходной путь, описанный в официальном объявлении, а не что-то, что сообщество вынуждено было разработать самостоятельно.
Тем не менее, речь идет о двух отдельных установках компилятора, находящихся в одном каталоге node_modules, связанных через псевдоним, который необходимо объяснять каждому новому члену команды, а также о конфигурации, которую в итоге придется изменить после выпуска версии 7.1. Назовем вещи своими именами: это технический долг без установленной даты погашения.
Вторая ловушка для тех, кто пропустил версию 6.0
Помимо отсутствующего API, существует еще одна проблема, подстерегающая команды, которые перешли сразу к версии 5.x, не проходя через 6.0.
TypeScript 7.0 полностью придерживается параметров по умолчанию, введенных в 6.0, и каждое предупреждение о устаревании, возникавшее в 6.0, превращается в серьезную ошибку в 7.0. Все это происходит одновременно:
strictтеперь включен по умолчанию.moduleтеперь по умолчанию равенesnext.
rootDir по умолчанию равен ./, а не определяется автоматически, поэтому если ваш файл tsconfig.json находится вне папки src, вам необходимо явно установить этот параметр, иначе компилятор неправильно оценит структуру исходного кода.types по умолчанию — это пустой массив, а не включение всех типов. Если ваш код зависит от глобальных переменных из установленных пакетов @types, вам нужно либо явно указать эти пакеты, либо восстановить прежнее поведение с использованием ["*"].target: es5, downlevelIteration, moduleResolution: node, baseUrl, а также режимы модулей amd, umd и systemjs. Использование любой из них теперь приводит к ошибке компиляции, точка.Из этого списка команда выделяет rootDir и types как два параметра, изменение которых с наибольшей вероятностью может застать людей врасплох, и это соответствует тому, чего можно ожидать на практике. В обоих случаях возникают ошибки, заполняющие терминал, которые создают впечатление, что сам компилятор сломан, а не указывают на то, что «изменился какой-то стандартный параметр». Именно такая путаница приводит к тому, что проблему считают ошибкой компилятора, вместо того чтобы исправить её простым изменением настроек в одной строке.
Также произошло более тихое изменение, направленное на тех, кто занимается манипуляциями строками на уровне типов. Теперь инференция типа шаблонных литералов рассматривает такой символ, как эмодзи, как одну единицу, вместо того чтобы разделять его на две единицы кода UTF-16. Это более интуитивная модель для большинства сценариев использования, но это нарушает совместимость с любыми пользовательскими вспомогательными типами в стиле Length, которые намеренно учитывали единицы кода UTF-16, а не видимые символы.
Практический вывод: если вы всё ещё используете версию 5.x, не переходите сразу на 7.0. Сначала обновитесь до 6.0. Эта промежуточная версия создана специально для того, чтобы распределить эти изменения, влияющие на совместимость, между двумя более небольшими обновлениями, вместо того чтобы сразу внедрить их все сразу.
Для кого на самом деле создано это обновление
В этом деталях, которые стоит рассмотреть подробнее.
Посмотрите список организаций, которые тестировали TypeScript 7 ещё до его официального выпуска и предоставляли отзывы по этому поводу: команда VS Code, собственные продукты Microsoft — Office, Teams, Power BI, а также группы Loop и Xbox, плюс Bloomberg, Canva, Figma, Google, Linear, Miro, Notion, Sentry, Slack и Vercel. Речь идет о кодовых базах объемом в миллионы строк, обслуживаемых специализированными командами по разработке инфраструктуры, которые месяцами создавали превью-версии и передавали найденные проблемы разработчикам до финального выпуска.
Для организаций такого масштаба этот выпуск действительно меняет способ выполнения работы, и цифры это подтверждают. Собственная команда News Services Microsoft сообщает о сокращении времени в 400 часов в месяц, ранее тратившегося на ожидание результатов автоматизированных тестов. Если раньше одна проверка типов занимала семь минут, то ее сокращение примерно в 8 раз кардинально меняет ежедневный ритм работы инженера.
Теперь сравните это с стартапом из пяти человек, использующим Nuxt с настроенным инструментом проверки кода, учитывающим типы. У них время проверки типов уже составляло 9 секунд. Обновление позволяет сократить это время примерно до 8 секунд, но взамен приводит к нарушению работы инструмента проверки кода, к тому, что проверка шаблонов Vue просто не может запуститься, а также к необходимости использования обходного решения в виде псевдонима в package.json, которое следующему сотруднику команды придётся им объяснять.
Преимущества в скорости растут пропорционально размеру вашей кодовой базы. Однако проблемы, возникающие в результате обновления, не растут — это фиксированные затраты, независимо от того, содержит проект десять файлов или десять миллионов.
Ничто из этого не указывает на плохие намерения. Это просто результат того, что проект оптимизируется с учетом обратной связи, которую он действительно может получить. Большие корпоративные кодовые базы находились в рамках программы предварительного тестирования, поэтому их проблемы были видны и измеримы задолго до запуска. Авторы экосистемы — в основном волонтеры, работающие над инструментами проверки кода, интеграциями в IDE и средствами сборки — оказались в положении тех, кто не участвовал принятии решений, а взамен получали лишь временные решения проблем совместимости и обещания, что всё будет исправлено в версии 7.1.
Огромная кодовая база превращает такое обновление в настоящий подарок. У маленькой базы приходится платить ту же фиксированную цену за гораздо меньшую отдачу. Именно это неравенство и является сутью всей ситуации.
Проверка готовности на сегодняшний день
Спустя месяц после общего выпуска вот примерное положение дел.
Если вы рассматриваете такой переход, наименее рискованным вариантом будет запуск 7.0 в качестве второй, не блокирующей процедуры проверки типов в CI наряду с той, что у вас уже есть. Это позволит получить точные данные о времени выполнения и чувство уверенности, не делая 7.0 основой для сборки. Как только обе процедуры будут работать корректно в течение примерно недели, вы сможете полностью перейти на 7.0.
Здесь нет преимуществ от того, чтобы быть одним из первых пользователей, поэтому всё равно стоит знать настройки, которые существуют: флаг --checkers определяет количество одновременно работающих процессов проверки типов, по умолчанию это 4. На сервере CI с ограниченными ресурсами обычно разумнее установить это значение на 1 или 2 процесса, вместо того чтобы оставить значение по умолчанию.
Воспроизведение сбоя за примерно пять минут
Ничего из этого не следует принимать на веру, и так и должно быть — сбои возникают достаточно редко и быстро, чтобы их можно было умышленно вызвать на временном тестовом проекте, прежде чем начинать работу с чем-то действительно важным.
Начните с чистой среды Vite React-TypeScript, добавьте настройку ESLint с поддержкой типов, а затем попробуйте принудительно установить более новый компилятор вместо нее:
npm create vite@latest ts7-probe -- --template react-ts
cd ts7-probe
npm install
npm install -D typescript-eslint eslint
npm install -D typescript@7
Большинство людей сталкиваются с проблемами уже на этапе установки. Пакет typescript-eslint, опубликованный в магазине npm, указывает диапазон совместимых версий, который ограничивается версией 6.1.0 и ниже, поэтому npm отклоняет попытку установки, выдавая ошибку ERESOLVE вместо мягкого предупреждения. На самом деле это более терпимый вариант обработки ошибок.
Более серьезные проблемы возникают, если игнорировать конфликт и всё равно заставить произойти установку. При наличии несовместимых пакетов при запуске инструмента lint происходит сбой в типсцрипт-естрее во время компиляции программы из-за попытки обратиться к свойству, которое больше не существует:
TypeError: Cannot read properties of undefined (reading 'Cjs')
at .../@typescript-eslint/typescript-estree/dist/create-program/shared.js
Обратите внимание, чего не говорится в этом сообщении. В нем нигде не упоминается TypeScript 7, не указывается несовместимость версий и нет фразы «несовместимая конфигурация». Это чисто внутренний сбой — что именно было описано в задаче 12518: автор запросил четкую, понятную для пользователя ошибку совместимости вместо стек-трейса, и на данный момент этот запрос остается открытым.
Теперь примените описанный ранее способ с использованием псевдонима и снова запустите те же команды. Инструмент Lint снова работает, поскольку он тихо взаимодействует с TypeScript 6.0 на фоне, тогда как команда npx tsc сама по себе продолжает использовать более быструю версию 7.0.
Поскольку вы настроили всё таким образом, стоит измерить время сборки под обеими версиями. Именно эти показатели, а не чьи-либо ещё тесты, должны влиять на ваше решение — и они почти наверняка окажутся гораздо менее значительными, чем цифры из VS Code, просто потому что ваш код не насчитывает два миллиона строк.
Что я извлек из этого
То, что делает TypeScript 7 особенным случаем, заключается в том, что существуют два противоречивых интерпретации его характеристик, обе из которых верны, при этом большинство тестов учитывает лишь одну из них.
Это серьезный пример инженерии компиляторов, который еженедельно возвращает реальные часы командам, терявшим их из-за медленной сборки. Это также релиз, в котором была выпущена лишь половина необходимого, причем этот факт был раскрыт глубоко в объявлении, оставив последствия для сотрудников, не имевших права голоса в планировании релизов.
Было бы полезно — и этого не было четко указано при выпуске — добавить в начале простое предложение: данный релиз готов к использованию в вашей системе сборки, а не в ваших инструментах, и вот что это конкретно означает для вас. Такое предложение технически существовало, но оно было спрятано далеко после таблицы с показателями производительности.
Версия 7.1 призвана действительно устранить этот разрыв. До тех пор разумный подход остается ограниченным: использовать высокую скорость там, где это не стоит денег, то есть в редакторе и в системах интеграции тестов, а все инструменты, которые по-прежнему напрямую используют компилятор, оставить без изменений.
Связанные статьи
- Роль «моста» TypeScript 6 на пути к нативному компилятору TS 7 — Узнайте, как TypeScript 6 обновляет стандартные настройки, механизмы разрешения модулей и синтаксис импорта, чтобы подготовить кодовые базы к более быстрому компилятору TypeScript 7, основанному на языке Go.