Головна / Статті

TypeScript 7 та порт для Go: швидша компіляція, ефективніше використання пам’яті та зворотний зв’язок від редактора.

TypeScript 7 замінює компілятор на нативний двигун Go. Паралельна компіляція, менше використання пам’яті, новий мовний сервер та умови міграції, які потрібно спочатку перевірити.

Видавець: REACTAPP.TOP8 хв читання1789 слів

Джерела: TypeScript 7 Is Here — And It Changes Much More Than the Compiler

Кожен, хто вже багато років працює з TypeScript, знає цей ритм. Спочатку пишеться код, потім редактор деякий час його аналізує, TypeScript обробляє проект, після чого запускається tsc, і знову доводиться чекати. У великому монорепозиторії ця пауза триває настільки довго, що вистачає часу на каву. Усе це не означає, що інструмент погано спроєктований. Його система типів та інструменти мови стали настільки потужними, що можуть обробляти дуже великі кодові бази, і саме тому він став настільки важливим у світі JavaScript. Але ця потужність мала свою ціну: у міру розширення проектів компілятор та сервер мови перетворилися на проблему продуктивності.

TypeScript 7.0 — це відповідь Microsoft, і важливо те, що основною зміною є не новий оператор, ключове слово чи синтаксичний трюк. Йдеться про двигун, який лежить в основі. Компілятор TypeScript раніше був написаний на самому TypeScript, що створювало цікаву рекурсивну структуру та добре функціонувало, проте це означало, що компілятор мусив працювати в межах моделі виконання JavaScript. Для версії 7 Microsoft переніс компілятор на мову Go, створивши нативну реалізацію, призначену для ефективного використання сучасного обладнання та паралелізму.

Ось що потрібно зрозуміти щодо цього випуску. TypeScript 7 — це насамперед не нова мова, а новий двигун для мови, якою вже пишуть люди, і саме це пояснення охоплює майже все інше щодо неї.

Показники швидкості

Основна цифра свідчить про вдесятеро більшу швидкість. Тестування від Microsoft показують, що повні збірки зазвичай виконуються в 8–12 разів швидше, залежно від проекту, причому це стосується великих реальних кодових баз, а не синтетичних мікротестів.

Час збірки навіть не є найбільш вражаючим результатом, адже прискорюється також сервер мови. У прикладі від Microsoft з кодовою базою VS Code час відкриття файлу, який містив помилку, зменшився з приблизно 17,5 секунд до появи першої помилки до менше ніж 1,3 секунди. Це зовсім інший досвід роботи, і у великих репозиторіях це має більше значення, ніж скорочення кількох сотень мілісекунд у процесі збірки для продакшну.

Використання кожного ядра

Сучасні процесори мають багато ядер, тоді як tsc історично працював лише з одним. TypeScript 7 значно краще їх використовує: парсинг, перевірка типів та генерація коду можуть виконуватися паралельно, де це можливо. Крім того, він додає кілька експериментальних параметрів:

--checkers
--builders
--singleThreaded

Перші два параметри забезпечують більш точний контроль над тим, як розподіляється паралельна робота, а --singleThreaded вимикає паралелізм за потреби, наприклад під час дебагування поведінки компілятора або роботи в обмеженому середовищі.

Найбільшу користь отримають монорепозиторії. Уявіть собі репозиторій із каталогом apps:

apps/
  web/
  admin/
  mobile/

та каталог пакетів:

packages/
  ui/
  api/
  config/
  utils/
  domain/

TypeScript раніше виконував величезну кількість послідовних операцій у межах цієї діаграми залежностей. З версією 7 більше з них може виконуватися одночасно. Тож справа не лише у тому, що компілятор став швидшим — він нарешті може ефективно використовувати апаратне забезпечення, на якому працює.

Пам’ять

Продуктивність — це не лише час обробки на CPU. Великі проекти на TypeScript можуть споживати кілька гігабайт оперативної пам’яті, особливо коли сервер мови працює разом із редактором, браузером, Docker та серверами розробки. Оприлюднені Microsoft тестування показують, що споживання пам’яті зменшується на 6%–26% у кількох великих проектах:

  • Bluesky: приблизно на 26% менше
  • VS Code: приблизно на 18% менше
  • tldraw: приблизно на 15% менше
  • Playwright: приблизно на 11% менше

Хоча прискорення складання проектів у десять разів може здатися незначним, кожен, хто бачив, як пам’ять ноутбука закінчується у великому монорепозиторії, розуміє його цінність.

Новий сервер мови

Більша частина привабливості TypeScript насправді не походить від tsc. Вона полягає у самому редакторі: автодоповнення, підказки типів під курсором, можливість переходу до визначення, перелік усіх посилань, зміна назви символа всюди, відображення помилок безпосередньо в коді та можливість їх виправлення одним кліком. Велика частина того, що робить сучасну розробку на JavaScript привабливою, ґрунтується саме на цьому.

У TypeScript 7 поставляється новий сервер мови, створений на основі Language Server Protocol, з використанням нативної реалізації та багатопотоковості. Команда продовжує розширювати його функціонал: з’явилися кодові лінзи, підказки всередині коду, семантичне підсвічування, сортування імпортів та видалення невикористаних імпортів, а також автоматичні імпорти, можливість переходу до визначення в коді та редагування JSX із автодоповненням тегів. Мета полягає не лише у прискоренні роботи tsc: весь процес від введення коду до отримання зворотного зв’язку стає швидшим, і саме це є найбільшою перевагою.

Детерміністичний вихід при паралелізмі

Одна з змін є менш привабливою, але технічно цікавою. TypeScript виконує багато внутрішніх операцій з типами, символами, об’єднаннями та деклараціями. Коли кілька процесів працюють одночасно, порядок створення внутрішніх об’єктів може змінюватися, що може вплинути на внутрішні ID та, відповідно, на порядок генерованих декларацій.

TypeScript 7 вирішує цю проблему шляхом детерміністичного впорядкування елементів на основі вмісту внутрішніх об’єктів, замість того щоб покладатися на порядок їх виникнення. Розглянемо цю функцію:

function foo(condition: boolean) {
  return condition ? 100 : 500;
}

Це може дати таке оголошення:

export declare function foo(
  condition: boolean
): 100 | 500;

І порядок об’єднання залишається стабільним, незалежно від того, як відбувається паралельна обробка. Більшість розробників цього не помітять, але саме ця інженерна реалізація робить високопаралельний компілятор надійним.

Це не версія з новими функціями

Усі, хто очікує чогось подібного:

type NewSuperPower<T> = ...

Чи то через велику кількість нових функцій мови, TypeScript 7 спочатку може здатися недостатньо потужним. Більшість зусиль було спрямовано на розвиток інфраструктури, а не на нові можливості системи типів. Команда роками створювала основу для наступного покоління TypeScript, і тепер воно існує. План розвитку передбачає подальшу роботу над функціями, покращення ергономіки, ще більше підвищення продуктивності та новий API компілятора після версії 7.0. Це оновлення краще розглядати як початок нової ери, а не як кінець попередньої.

Умови для розробників інструментів

Саме тут справи стають цікавими для тих, хто створює інструменти. TypeScript 7.0 не постачається зі старим API компілятора, і команда очікує, що версія 7.1 введе новий API. Це має велике значення, адже більша частина екосистеми не просто використовує tsc — лінтери, компілятори фреймворків, сервіси мови та інструменти збірки програмно взаємодіють з TypeScript.

Це одна з причин, чому TypeScript 6 та 7 можуть поки що існувати поруч. Microsoft ввів @typescript/typescript6, щоб полегшити перехід, тож проект може зберігати версію 6 для інструментів, які все ще потребують її API, водночас окремо використовуючи компілятор версії 7. Оновлення компілятора не завжди є настільки простим, як зміна одного рядка:

{
  "devDependencies": {
    "typescript": "^7.0.0"
  }
}

У великих екосистемах компілятор є інфраструктурою, а інфраструктура має залежності.

Ще один обмеження стосується фреймворків та інструментів, які вбудовують TypeScript у власні процеси компіляції чи сервіси мови. Команда називає Vue, MDX, Astro, Svelte та Angular серед тих інструментів, де підтримка нової архітектури сервісів мови все ще розвивається, і знову саме відсутність стабільного програмного API є причиною цього. Звичайний додаток на React та TypeScript може бути легко переведений, без особливих проблем. Однак інтеграція з складними фреймворками, плагінами компілятора чи плагінами сервісів мови створює значно складніші умови. Варто перевірити це перед оновленням будь-якого великого продакшн-репозиторію.

TypeScript 6 як перехідний етап

TypeScript 6 ніколи не був просто версією, що передувала 7. Його навмисно створили як місток між версіями. Кілька старих опцій компілятора були позначені як застарілі та повністю видалені у версії 7, тому команда рекомендує їх видалити перед оновленням. Використання проміжної версії, як показано нижче, краще, ніж розглядати версію 7 як окреме оновлення:

TypeScript 5.x
      ↓
TypeScript 6
      ↓
TypeScript 7

Будь-які попередження про відміну, які генерує проект під TypeScript 6, заслуговують на увагу. Це фактично сповіщення про міграцію, надіслані з майбутнього.

Чому важливий цикл зворотного зв’язку

TypeScript зникає після компіляції, тому розробники фронтенду рідко вважають його частиною часу виконання додатку. Проте він сильно впливає на час виконання під час розробки. Кожного разу, коли редактор проходить через такий цикл:

type something
↓
autocomplete appears
↓
you navigate to a definition
↓
you rename a symbol
↓
you save
↓
CI runs
↓
the project gets type-checked

TypeScript бере участь у кожному процесі, і його роль зростає разом із складністю додатків. Затримка у 100 мс не має значення, але затримка у 10 секунд — так; очікування протягом 30 секунд змінює спосіб роботи людини, а перевірка коду за допомогою CI протягом п’яти хвилин впливає на роботу всієї команди. Тож основною перевагою TypeScript 7 є не в десятикратній швидкості компіляції, а у скороченні часу між написанням коду та перевіркою його коректності.

Спробувати

Для нового проекту TypeScript 7 безумовно вартий розгляду. Для існуючого проекту краще обрати більш обережний підхід. Почніть з його встановлення як залежності для розробки:

npm install -D typescript@7

Потім виконайте перевірку типу без виведення:

npx tsc --noEmit

і перевірте результати, розглянувши наступні аспекти:

  1. Помилки компілятора
  2. Застаріла конфігурація
  3. Сумісність інструментів збірки
  4. Інтеграція з ESLint
  5. Інтеграція з фреймворком
  6. Поведінка IDE
  7. Продуктивність CI
  8. Споживання пам’яті

У великому monorepo виконайте тестування до та після змін, використовуючи щось на кшталт:

time npx tsc --build

І порівняйте результат із поточною версією TypeScript. Окрема увага не повинна приділятися лише кінцевій цифрі. Важлива вся сукупність досвіду розробки.

Повторна будова основи

TypeScript 7 вирізняється серед інструментів фронтенду тим, що команда пропустила звичайний крок додавання нових функцій до існуючої архітектури та замість цього повністю перебудувала основу. Мові не потрібно було переосмислення, а ось інфраструктурі — так. Часовий момент також є доцільним: у масштабних проектах на JavaScript поширені монорепозиторії, скрізь є API з типовою безпекою, існують розумніші редактори, інструменти для програмування на основі ШІ, які потребують семантичних даних, а розробники очікують майже миттєвих відповідей. Компілятор, достатньо швидкий для застосунку 2015 року, не обов’язково зможе впоратися з монорепозиторієм 2026 року.

Простіше кажучи, ця версія визнає, що старий дизайн працював ефективно, але сучасне програмне забезпечення вийшло за його межі. Замість того, щоб відмовитися від системи типів, яка вже подобається розробникам, команда перебудувала те, що працює під капотом. Саме тому ця версія має більше значення, ніж може здатися з огляду на її видимий перелік функцій. Це основа для подальшого розвитку TypeScript, а також швидший tsc. Якщо обіцяні покращення поширяться на весь екосистему, найцікавіші функції TypeScript можуть з’явитися навіть не у версії 7. Вони можуть стати практичними лише тому, що версія 7 достатньо швидка для їх реалізації.

Головною темою є паралелізм, виконання на рівні операційної системи, зниження використання пам’яті, новий мовний сервер, детермінований результат компіляції та основи для майбутніх інструментів. Для тих, хто підтримує великі за обсягом проекти на TypeScript, це, мабуть, має більшу цінність, ніж ще один інструмент для роботи з типами.