Раз вы открыли эту статью, вы наверняка со мной согласны: иногда TypeScript компилируется мучительно долго.
С тем же самым столкнулся @_chenglou — крутой разработчик, на которого я равняюсь (он работал над React, Messenger, ReasonML и ReScript, а сейчас — над Midjourney и Pretext).
А ещё он пользуется Sury — самой быстрой библиотекой валидации схем, которую я поддерживаю, — и завёл вот этот issue: “Large TS types cause type inference slowdown”.
Ну… неприятно. Но я знал, что есть ArkType и что в системе типов TS люди собирали и не такое — вплоть до Doom. Значит, тормоза лечатся, а не заложены в фундамент. Ниже — рецепт, по которому я шёл. Его можно применить и к своей библиотеке.
Прежде чем начать — результаты. Это количество инстанцирований типов, измеренное через @ark/attest:
Операция |
Было |
Стало |
Быстрее |
|---|---|---|---|
Описать объект из 10 полей |
1409 |
343 |
4.1× |
Описать объект из 5 полей (часть опциональных) |
17916 |
10557 |
1.7× |
Описать объект с вложенностью в 3 уровня |
31013 |
20419 |
1.5× |
Описать юнион из 5 объектов |
67580 |
53173 |
1.3× |
Достать |
7842 |
501 |
15.7× |
Достать |
6767 |
501 |
13.5× |
Достать |
7732 |
501 |
15.4× |
Описать + достать (объект из 10 полей) |
9446 |
844 |
11.2× |
Смёржить + достать output |
13651 |
7039 |
1.9× |
Заголовок — про те самые 15.7× на S.Output. Извлечение — самая частая операция: каждый type X = S.Output<typeof schema> в вашем коде платит именно за это.
Поехали. В рецепте три шага.
1. Сначала зафиксировать
Прежде чем что-то менять, нужен способ понять, что вы это не сломали. Для такой библиотеки это значит тесты на типы:
import { expectTypeOf } from "vitest"; import * as S from "sury"; const user = S.schema({ id: S.string, age: S.number }); // Фиксируем выведенный тип. Поедет - тест упадёт. expectTypeOf<S.Output<typeof user>>().toEqualTypeOf<{ id: string; age: number; }>();
Раньше я брал для этого ts-expect, но переехал на тайп-тесты из Vitest (expectTypeOf выше), чтобы убрать лишнюю зависимость. Так или иначе, тесты у меня уже были — и, признаю, они себя полностью окупили. Оптимизация типов легко превращает { a: string } в { a?: string }, и никто вам об этом не сообщит. Ловят такое только тесты.
2. Померить до того, как что-то трогать
Если вы хотите что-то улучшить, это надо сначала померить — иначе потом не понять, улучшили вы хоть что-нибудь или нет.
Для этого я взял Attest (@ark/attest) от создателей ArkType. Меня очень вдохновляет их уровень владения TS, и, честно говоря, сам я в оптимизации на уровне типов не так силён. Хорошо, что силён в другом. ?
Он считает, во сколько инстанцирований типов обходится выражение, и фиксирует это как бейзлайн:
import { bench } from "@ark/attest"; import * as S from "sury"; bench("define a user schema", () => { return S.schema({ id: S.string, age: S.number }); }).types([230, "instantiations"]);
Бонус: занесите эти бейзлайны в CI — и любая будущая регрессия завалит сборку.
3. Тяжёлую работу отдать Claude
Третий шаг оказался самым простым: я попросил Claude найти оптимизации, которые сильнее всего снизят число инстанцирований.
Фикс оказался крошечным. Чтобы достать тип из схемы, S.Output / S.Input матчились по всему типу Schema<…>. А тип этот здоровенный: большой объект с несколькими перегрузками with, пересечённый с юнионом всех вариантов схемы. То есть TypeScript разворачивал это целиком на каждое извлечение, и цена росла вместе со схемой:
// Было: матчим всю форму Schema<…>, только чтобы достать обратно Output type Output<T> = T extends Schema<infer Output, unknown> ? Output : never;
Но в каждой схеме Sury уже есть поле ~standard (маркер Standard Schema), в котором готовые типы и лежат. Так что достаточно заглянуть сразу туда, а не выводить всё заново из общей формы:
// Стало: матчим одно поле, в котором тип уже лежит type Output<T> = T extends { "~standard": { types?: { output: infer Output } } } ? Output : never;
Теперь извлечение стоит одинаково, какого бы размера ни была схема. Именно это изменение и даёт большую часть тех 11–16× из таблицы выше.
А вам это вообще надо?
Зависит от ситуации (мой любимый ответ). Но скорость обратной связи значит всё больше — по вашему коду теперь итерируется ещё и AI. Если TypeScript в вашем проекте компилируется медленно, тем же способом можно найти медленные места и заняться ими.
Подводя итог
Одна оговорка: 15.7× — это падение числа инстанцирований типов, а не секунд. Реальную компиляцию я не замерял. Но инстанцирования — это и есть та работа, которую tsc делает при проверке типов, так что их количество вполне честно отражает то, что вы чувствуете в редакторе. ?
Надеюсь, было полезно. Загляните в Sury — самую мощную библиотеку схем в экосистеме TS. Подписывайтесь на меня в X (@dzakh_dev) и задавайте вопросы в комментариях!
Комментарии (11)

Zukomux
17.08.2026 08:27И что? И как? К чему статья-то? По-факту, все свелось к оптимизации через ИИ. Но я уверяю вас, как только вы пытаетесь сами такое писать или заставить команду делать также, вы поймёте, что ваших временных затрат будет в разы больше, чем затрат на компиляцию. Тем более, что на подходе TS7 который реально быстрее, в отличии от таких вот подходов

DZakh Автор
17.08.2026 08:27Статья про то, что для оптимизации с помощью ИИ нужен фидбек луп. И то что есть инструменты как померить производительность вывода типов.

Zukomux
17.08.2026 08:27Статья называется “Как я ускорил…” Не вижу вашу работу по оптимизации. Интересно было-бы почитать про ast, про то, как работает компилятор ts и на этом основании применять какие-то техники оптимизации, а не про то, что любая llm выдаст за 5 минут работы

cmyser
17.08.2026 08:27тем же самым столкнулся @_chenglou — крутой разработчик, на которого я равняюсь (он работал над React, Messenger, ReasonML и ReScript, а сейчас — над Midjourney и Pretext).
Сейчас бы равняться на худшие ( реакт ) продукты в индустрии
https://b-on-g.github.io/smalljs/section=versus/a=mol/b=react
ijustwanttobeacool
Начало статьи меня затянуло, стало интересно что же такое ArkType и как он может дать 15x производительность, но статья резко заканчивается на том, что вы вместо готовых сгенерированных типов использовали выведение типов в "рантайме" и ArkType тут вообще не при делах :(
DZakh Автор
Интересно что вы ожидали увидеть? Я может быть знаю)
DZakh Автор
Тут не ArkType, а Attest от разработчиков ArkType. Статья в целом актуальна только для авторов библиотек)