TypeScript-проекты растут. Количество файлов множится. Зависимости запутываются. И в конце концов ваша сборка упирается в стену, которая не имеет ничего общего со сложностью вашей логики, но напрямую связана с тем, что компилятору нужно прочитать целую вселенную, прежде чем он сможет записать хотя бы один файл деклараций.
TypeScript 6.0 решает эту проблему с помощью isolatedDeclarations. Эта функция переосмысливает процесс создания .d.ts файлов. Вместо того чтобы привязывать генерацию деклараций к полному конвейеру проверки типов, она позволяет компилятору создавать эти файлы,
Это также меняет набор доступных инструментов. Транспиляторы вроде esbuild и swc уже работают молниеносно, превращая TypeScript в JavaScript, но многие команды всё равно запускают tsc отдельно только для того, чтобы создать .d.ts файлы. С isolatedDeclarations эти быстрые инструменты смогут выполнять обе задачи. Им не нужно воспроизводить всю систему типов TypeScript для генерации деклараций; им достаточно разобрать синтаксис и скопировать предоставленные вами явные типы. Это делает сквозную сборку TypeScript с использованием альтернативных цепочек инструментов гораздо более жизнеспособной.
Распределенные и инкрементальные сборки также упрощаются. В процессах непрерывной интеграции удаленный кэш или шардированная сборка могут генерировать декларации для пакета, не скачивая предварительно весь его граф транзитивных зависимостей. Если типы в исходном коде указаны явно, у шарда сборки будет всё необходимое.
Что остается прежним
Ограничение распространяется только на экспорты. Внутри модуля всё работает как обычно. Локальные переменные, приватные члены классов и неэкспортируемые вспомогательные функции всё еще могут полагаться на полный вывод типов. TypeScript без проблем выведет тип переменной цикла или параметра замыкания.
export function calculateTotal(items: Item[]): number {
// Local variable: inference is fine
const taxRate = 0.08;
// Private class member inside a local class: inference is fine
class Helper {
private cache = new Map();
}
return items.reduce((sum, item) => sum + item.price * (1 + taxRate), 0);
}
Только сигнатуре экспортируемой функции потребовалось аннотирование. Внутренняя логика остается гибкой и выразительной. Это делает нагрузку на разработчика приемлемой. Вы не переходите на полностью явный стиль везде; вы просто формализуете контракт на границе каждого модуля.
Подходит ли это для вашей кодовой базы?
Внедрение isolatedDeclarations меняет распределение вашего времени. Вы тратите чуть больше усилий при написании экспорта, но взамен перестаете «платить проценты» при каждой сборке. Для авторов библиотек это зачастую легко обосновать: публичные API и так, скорее всего, должны быть аннотированы. Для разработчиков приложений, работающих внутри закрытого монорепозитория, первоначальные затраты могут показаться излишней формальностью. Но если ваша команда измеряет время сборки перерывами на кофе, такая сделка быстро становится выгодной.
Вы можете внедрять это постепенно. Включите флаг, запустите компилятор и исправьте ошибки, которые он обнаружит в экспортируемых символах. Сообщения об ошибках точно укажут, какие типы, доступные публично, являются неявными. Исправьте их, не трогайте внутренности и наблюдайте, как ускоряется этап генерации деклараций.
Одно стоит помнить: этот флаг не ускоряет сам механизм проверки типов TypeScript. Если вам нужна более быстрая обратная связь в редакторе или ускорение выполнения tsc --noEmit, вам всё равно потребуются project references, более строгое включение файлов или другие архитектурные решения. isolatedDeclarations нацелен именно на генерацию .d.ts файлов. Это оптимизация сборки, а не оптимизация проверки типов.
Главный вывод
isolatedDeclarations требует от вас относиться к публичным типам как к полноценным артефактам. Перестаньте заставлять компилятор выводить их. Записывайте их явно. Как только вы это сделаете, компилятору больше не придется прочесывать весь ваш граф зависимостей каждый раз, когда нужно сгенерировать файл декларации. Генерация происходит параллельно, такие инструменты, как esbuild и swc, справляются с полными рабочими процессами TypeScript, и сборки вашего монорепозитория перестают тормозить.
Затраты смещаются с времени сборки на время написания кода. Для большинства растущих команд это выгодный обмен.
