Чому порт Go від TypeScript 7 зламав інструменти лінтингу та фреймворків
Пояснює, чому швидший компілятор 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. І є бібліотека, яку інші інструменти використовують як залежність. Інструменти для перевірки синтаксису, трансформатори тестів, модифікатори коду на основі AST та перевірювачі шаблонів не звертаються до 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 plus 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 для loaders, усі чекають на версію 7.1.Уважно подивіться, що є у цьому списку. Серед них немає жодних нішевих чи екзотичних інструментів — це стандартний набір засобів типової команди фронт-енд розробників сьогодні.
Сам компілятор є стабільним. Однак екосистема навколо нього — ні. Це два різні стани випуску, які ділять один і той самий номер версії.
Відповідь Microsoft: встановити два компілятори одночасно
Microsoft передбачив ці проблеми та створив обхідний шлях, замість того щоб залишати команди самостійно шукати рішення. Вони опублікували @typescript/typescript6 — пакет сумісності, який містить виконуваний файл tsc6 та відновлює доступ до інтерфейсу API версії 6.0. Це дозволяє старому та новому компіляторам існувати разом, без конфліктів у назвах їхніх бінарних файлів.
Причина необхідності цього обходу полягає у тому, що інструменти на кшталт typescript-eslint розрішують ім’я TypeScript за назвою пакета через peer dependency. Тож рекомендованим рішенням є використання npm alias для перенаправлення цього імені.
Повна налаштування подвійного компілятора виглядає так:
{
"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 із налаштуванням lint з підтримкою типів. Час перевірки типів у них вже становив 9 секунд. Оновлення дозволяє заощадити ще близько 8 секунд, але в обмін вимагає несправної системи lint, перевірювача шаблонів Vue, який просто не може працювати, та рішення у вигляді аліасу в package.json, яке наступному інженеру, що приєднається до команди, доведеться пояснювати.
Перевага у швидкості зростає разом із розміром вашої кодової бази. Проблеми ж зовсім не зростають — це фіксовані витрати, які існують незалежно від того, чи має ваш проект десять файлів, чи десять мільйонів.
Жоден із цих фактів не свідчить про погані наміри. Це просто наслідок того, що проект оптимізується під зворотний зв’язок, який він насправді може спостерігати. Великі кодові бази корпорацій були включені до програми попереднього перегляду, тож їхні проблеми були видимими та вимірюваними ще задовго до запуску. Ті, хто підтримує екосистему — переважно волонтери, які працюють над інструментами перевірки коду, інтеграціями в IDE та засобами компіляції — опинилися поза процесом прийняття рішень, у якому не мали права голосу, а натомість отримали лише тимчасове рішення проблеми сумісності та обіцянку, що все буде виправлено у версії 7.1.
Велика кодова база перетворює це оновлення на справжній подарунок. Мала кодова база ж оплачує ті самі постійні витрати за значно меншу винагороду. Саме цей дисбаланс є суттю проблеми.
Перевірка готовності станом на сьогодні
Минув місяць з моменту загального доступу, і ось приблизний стан справ.
Якщо ви розглядаєте такий крок, найменш ризикованим варіантом є запуск 7.0 як другої, неблокуючої задачі перевірки типів у CI поруч із тією, яка вже у вас є. Це дасть вам точні дані про час виконання та впевненість, не роблячи 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 визначає діапазон версій peer dependency, який обмежується нижче версії 6.1.0, тому npm відмовляється у його встановленні, показуючи помилку ERESOLVE замість м’якого попередження. Насправді це є більш толерантним способом виявлення проблеми.
Ще гірші наслідки виникають, якщо ігнорувати конфлікт та все одно примусово встановлювати програму. Коли на місці знаходяться несумісні пакети, запуск lint призводить до збою в typescript-estree під час складання програми через спробу отримати доступ до властивості, яка більше нічого не повертає:
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 призначена саме для того, щоб усунути цю прогалину. До того часу розумний підхід є обмеженим: використовувати швидкість там, де це не коштує нічого — у вашому редакторі та в системах CI, а всі інструменти, які досі безпосередньо імпортують компілятор, залишати без змін.
Пов’язана література
- Роль мосту TypeScript 6 на шляху до нативного компілятора TS 7 — Дізнайтеся, як TypeScript 6 оновлює стандартні налаштування, механізми розрішення модулів та синтаксис імпорту, щоб підготувати кодові бази до швидшого компілятора TypeScript 7, заснованого на Go.