Esbuild ориентирован на максимально быстрые преобразования JavaScript
и TypeScript с упором на транспиляцию и бандлинг. Его архитектура
сознательно исключает полноценную работу с системой типов TypeScript,
включая генерацию декларационных файлов .d.ts.
Ключевая причина заключается в том, что esbuild выполняет только
синтаксический разбор и преобразование кода, не проводя полноценный
type-checking. Генерация .d.ts требует семантического
анализа программы, разрешения типов, вычисления экспорта интерфейсов и
пересечения модулей — это область ответственности TypeScript Compiler
(tsc).
Таким образом, esbuild:
Попытка встроить генерацию .d.ts противоречила бы его
философии минимальной задержки и предсказуемой скорости.
.d.ts файлов и требования к их генерацииФайлы деклараций TypeScript представляют собой описание контрактов модулей без реализации. Они используются внешними потребителями библиотеки для типизации без доступа к исходному коду.
Генерация таких файлов требует:
tsconfig опций (declaration,
emitDeclarationOnly, composite).Эти операции выполняются TypeScript Compiler, а не инструментами бандлинга вроде esbuild.
В современном toolchain принято разделять задачи:
Это разделение обусловлено тем, что:
.d.ts через tscОсновной и канонический способ — использование TypeScript Compiler в режиме emit-only для деклараций.
// tsconfig.json
{
"compilerOptions": {
"declaration": true,
"emitDeclarationOnly": true,
"outDir": "dist/types",
"strict": true
},
"include": ["src"]
}
Запуск:
tsc -p tsconfig.json
В результате формируется:
.d.ts файлы для каждого модуля;Типичный production-пайплайн разделяет сборку JavaScript и генерацию типов:
esbuild src/index.ts --bundle --platform=node --outdir=dist
tsc -p tsconfig.json --emitDeclarationOnly
Такой подход обеспечивает:
При параллельном использовании esbuild и tsc часто возникает проблема несоответствия структуры выходных файлов.
esbuild может:
tsc же:
Поэтому декларации обычно генерируются из исходного кода, а не из результата esbuild.
Для библиотек часто применяются специализированные инструменты поверх TypeScript Compiler:
Позволяет собрать единый .d.ts файл:
dts-bundle-generator -o dist/index.d.ts src/index.ts
Используется для:
Инструмент tsup объединяет esbuild и генерацию типов:
.d.ts;Пример:
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["src/index.ts"],
dts: true,
format: ["esm", "cjs"],
clean: true
});
Архитектурные ограничения:
Отсутствие полной типовой модели esbuild не хранит расширенную информацию о типах.
Скорость как приоритет Любая типовая система снизила бы производительность на порядок.
Сложность TypeScript языка Conditional types, mapped types, template literal types требуют полноценного интерпретатора типов.
Отсутствие необходимости в рамках bundler-а Бандлер решает задачу упаковки JS, а не описания API.
Транспиляция (esbuild):
Генерация деклараций (tsc):
Типичный workflow публикации пакета:
Исходный код:
src/
index.ts
utils.tsСборка JS:
esbuild src/index.ts --bundle --format=esm --outdir=distГенерация типов:
tsc --declaration --emitDeclarationOnly --outDir dist/typesФинальная структура:
dist/
index.js
utils.js
dist/types/
index.d.ts
utils.d.ts.d.ts после сборки esbuild;TypeScript предоставляет механизм масштабируемой генерации деклараций через project references:
{
"compilerOptions": {
"composite": true,
"declaration": true
}
}
Это позволяет:
.d.ts;esbuild в этом процессе не участвует, так как не поддерживает dependency graph type-aware компиляции.
Современная практика строится на разделении:
Попытка перенести генерацию .d.ts в esbuild нарушает это
разделение и приводит к усложнению без практического выигрыша в
производительности или точности.