tsconfig.json и его взаимодействие с .swcrc

В экосистеме TypeScript файл tsconfig.json традиционно выступает центральной точкой конфигурации компилятора tsc. Он определяет правила анализа типов, структуру проекта, пути модулей, целевую версию JavaScript и множество других параметров, влияющих на поведение компиляции.

В проектах, где вместо стандартного компилятора используется SWC, роль tsconfig.json меняется: он перестаёт быть источником трансформации кода и становится источником метаданных для понимания структуры TypeScript-проекта, при этом реальная трансформация управляется через .swcrc.

Такое разделение приводит к важному архитектурному принципу:

  • tsconfig.json — описание проекта и типизации
  • .swcrc — описание трансформации кода

Архитектурное разделение ответственности

SWC изначально спроектирован как высокопроизводительный транспайлер, который не обязан повторять поведение tsc во всех деталях. Это отражается в разделении конфигураций:

tsconfig.json отвечает за:

  • включение файлов (include, exclude, files)
  • настройку модульного резолвинга TypeScript
  • алиасы путей (compilerOptions.paths)
  • режим проекта (composite, incremental)
  • строгую типизацию (strict, noImplicitAny)
  • декларации типов (declaration, emitDeclarationOnly)

.swcrc отвечает за:

  • трансформацию TypeScript в JavaScript
  • выбор target ECMAScript
  • преобразование JSX
  • поддержку decorators
  • генерацию sourcemap
  • minification (при включении SWC minifier)
  • совместимость с различными рантаймами (Node, browser)

Такое разделение позволяет SWC игнорировать тяжёлую часть type-checking и сосредоточиться на скорости преобразования AST.

Как SWC использует tsconfig.json

Несмотря на то что SWC не выполняет type-checking, он частично читает tsconfig.json. Это происходит не для валидации типов, а для извлечения информации о структуре проекта.

Основные сценарии использования

  1. Разрешение путей (paths, baseUrl)

Одна из ключевых причин, почему SWC обращается к tsconfig.json, — поддержка алиасов.

{
  "compilerOptions": {
 "baseUrl": ".",
 "paths": {
   "@app/*": ["src/app/*"],
   "@shared/*": ["src/shared/*"]
 }
  }
}

SWC использует эти данные, чтобы корректно переписывать импорты при трансформации.

  1. Определение входных файлов проекта

Поле include и exclude может использоваться инструментами вокруг SWC (например, сборщиками), чтобы определить набор файлов для обработки:

{
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

Важно: сам SWC не всегда напрямую интерпретирует эти поля, но они активно используются интеграциями (Next.js, Vite-плагины, custom build pipelines).

  1. Согласование типов и трансформации

SWC может учитывать некоторые флаги, влияющие на синтаксис TypeScript:

  • jsx
  • experimentalDecorators
  • useDefineForClassFields
  • target

Однако критическое различие заключается в том, что эти параметры дублируются в .swcrc и могут конфликтовать.

Конфигурация .swcrc как основной источник трансформации

Файл .swcrc является основным конфигурационным файлом SWC. Пример:

{
  "jsc": {
 "parser": {
"syntax": "typescript",
"tsx": true,
"decorators": true
 },
 "transform": {
"legacyDecorator": true,
"react": {
  "runtime": "automatic"
}
 },
 "target": "es2020"
  },
  "module": {
 "type": "es6"
  },
  "sourceMaps": true
}

Ключевой принцип взаимодействия

Если tsconfig.json описывает проект, то .swcrc описывает поведение трансформации.

SWC не объединяет их автоматически в единую модель, поэтому возникает слой интеграции, который решает:

  • какие данные взять из tsconfig.json
  • какие игнорировать
  • как разрешить конфликты

Конфликты между tsconfig.json и .swcrc

На практике часто возникает ситуация, когда одинаковые концепции задаются в двух местах.

  1. target

tsconfig.json:

{
  "compilerOptions": {
 "target": "ES2022"
  }
}

.swcrc:

{
  "jsc": {
 "target": "es2020"
  }
}

В этом случае приоритет имеет .swcrc, так как именно он управляет трансформацией.

  1. JSX runtime

tsconfig.json:

{
  "compilerOptions": {
 "jsx": "react-jsx"
  }
}

.swcrc:

{
  "jsc": {
 "transform": {
"react": {
  "runtime": "classic"
}
 }
  }
}

Поведение определяется SWC-конфигурацией, а tsconfig.json влияет только на IDE и type-checking.

  1. Decorators

TypeScript и SWC исторически различаются в реализации декораторов:

  • TypeScript использует свой стандарт и флаг experimentalDecorators
  • SWC имеет собственную модель через legacyDecorator
{
  "jsc": {
 "parser": {
"decorators": true
 },
 "transform": {
"legacyDecorator": true
 }
  }
}

При расхождении поведения именно .swcrc определяет итоговую трансформацию.

Роль tsconfig.json в SWC-пайплайнах

В реальных сборках tsconfig.json часто используется не самим SWC, а инструментами вокруг него.

Next.js

В Next.js tsconfig.json используется для:

  • резолвинга алиасов
  • определения корня проекта
  • настройки путей модулей

SWC при этом выполняет транспиляцию через встроенный pipeline Next.js.

Vite + SWC

В связке Vite + SWC:

  • tsconfig.json читается плагинами для резолвинга импортов
  • .swcrc управляет трансформацией
  • Vite выполняет bundling поверх результата SWC

NestJS + SWC

В NestJS SWC используется как ускоренная замена tsc, при этом:

  • tsconfig.json определяет структуру проекта
  • .swcrc отвечает за emit JavaScript

Порядок приоритета конфигураций

В типичном SWC-пайплайне можно выделить следующую иерархию:

  1. .swcrc — трансформация AST
  2. настройки bundler’а (Webpack, Vite, Next.js)
  3. tsconfig.json — структура и типизация

Это означает, что:

  • tsconfig.json не может переопределить поведение трансформации SWC
  • .swcrc не обязан учитывать все TypeScript-опции
  • интеграционный слой отвечает за согласование

Алиасы и резолвинг модулей

Одним из наиболее важных пересечений является работа с импортами.

Пример tsconfig.json

{
  "compilerOptions": {
 "baseUrl": ".",
 "paths": {
"@components/*": ["src/components/*"]
 }
  }
}

Поведение в SWC

SWC сам по себе не выполняет полноценный module resolution. Вместо этого:

  • плагины переписывают импорты
  • bundler использует tsconfig.json
  • иногда используется отдельный резолвер (tsconfig-paths)

Таким образом, алиасы не являются функцией SWC напрямую, а зависят от окружения.

Разделение type-checking и трансформации

Ключевой концепт взаимодействия:

  • SWC не проверяет типы
  • tsconfig.json не влияет на кодогенерацию SWC

Это приводит к необходимости параллельного запуска TypeScript:

swc src -d dist
tsc --noEmit

Такой подход разделяет:

  • скорость трансформации (SWC)
  • точность проверки типов (tsc)

Особенности монорепозиториев

В монорепозиториях взаимодействие становится сложнее:

Множественные tsconfig.json

  • базовый tsconfig.base.json
  • пакетные tsconfig.json
  • проектные override-файлы

SWC обычно работает в контексте одного .swcrc, поэтому:

  • типовая конфигурация TS может быть глубже иерархии
  • SWC использует упрощённый слой резолвинга

Project references

TypeScript поддерживает:

{
  "references": [
 { "path": "../shared" }
  ]
}

SWC не интерпретирует это напрямую, поэтому сборка зависит от внешнего оркестратора.

Практическая модель взаимодействия

Логически взаимодействие можно описать как два параллельных слоя:

  • слой анализа (tsconfig.json)
  • слой трансформации (.swcrc)

Они пересекаются только в ограниченных точках:

  • пути модулей
  • JSX/TSX синтаксис
  • базовые синтаксические флаги

Все остальные аспекты существуют независимо.

Поведение при отсутствии tsconfig.json

Если tsconfig.json отсутствует:

  • SWC продолжает работать без ограничений
  • используется только .swcrc
  • алиасы и project structure не определяются автоматически

Это ещё раз подчёркивает, что tsconfig.json не является обязательным для SWC как трансформера.

Поведение при отсутствии .swcrc

Если .swcrc отсутствует:

  • SWC использует дефолтные настройки
  • TypeScript код может транслироваться с базовыми параметрами
  • поведение становится менее предсказуемым в сложных проектах

Влияние на инструменты сборки

Разные сборщики по-разному комбинируют конфигурации:

Webpack + SWC loader

  • .swcrc — основной источник трансформации
  • tsconfig.json — используется через ts-loader или резолверы

Vite

  • SWC плагин читает .swcrc
  • Vite читает tsconfig.json для алиасов

Turbopack

  • глубоко интегрирует оба файла
  • оптимизирует пересечение конфигураций

Общая модель согласования

Финальная модель взаимодействия выглядит как:

  • tsconfig.json описывает семантику проекта
  • .swcrc описывает синтаксическую трансформацию
  • сборщик объединяет оба слоя в единый pipeline

Разделение позволяет добиться высокой скорости трансформации без потери гибкости проектной структуры.