Поддержка TypeScript в SWC

SWC поддерживает TypeScript как язык трансформации, но принципиально не выполняет семантическую проверку типов. Его модель работы основана на быстром разборе TypeScript-синтаксиса и последующем удалении типов с трансформацией к целевому JavaScript, что делает его ближе к Babel, чем к tsc в части ответственности за типобезопасность.

SWC рассматривает TypeScript как надмножество JavaScript на уровне синтаксического анализа. Внутри компилятора реализован полноценный парсер TS/TSX, способный обрабатывать типы, интерфейсы, дженерики, перечисления и современные конструкты ECMAScript, после чего вся типовая информация полностью удаляется на этапе трансформации.

Обработка TypeScript в SWC разделяется на несколько стадий:

1. Парсинг (Parsing)

  • анализ .ts и .tsx файлов;
  • построение AST с сохранением TypeScript-специфичных узлов;
  • поддержка JSX в .tsx без дополнительной конфигурации парсеров.

2. Трансформация (Transformation)

  • удаление аннотаций типов;
  • преобразование синтаксиса в JavaScript выбранного стандарта (ES5, ES2018, ESNext);
  • обработка модулей (ESM/CommonJS).

3. Генерация кода (Codegen)

  • вывод оптимизированного JavaScript;
  • минимизация накладных расходов на структуру AST.

Ключевое отличие: отсутствует отдельная стадия type-checking, что существенно ускоряет обработку.

Конфигурация TypeScript в SWC

Основная конфигурация задаётся через .swcrc. Поддержка TypeScript включается через блок jsc.parser:

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": true,
      "decorators": true,
      "dynamicImport": true
    }
  }
}

Параметры парсера

  • syntax: “typescript” — активирует TypeScript-режим;
  • tsx: true — включает поддержку JSX внутри TS;
  • decorators: true — разрешает синтаксис декораторов;
  • dynamicImport: true — поддержка import() выражений.

Дополнительно часто используется блок transform:

{
  "jsc": {
    "target": "es2020",
    "parser": {
      "syntax": "typescript",
      "tsx": true
    },
    "transform": {
      "react": {
        "runtime": "automatic"
      }
    }
  }
}

Удаление типов (Type Stripping)

Основная операция SWC над TypeScript — удаление типов без их проверки.

Пример исходного кода:

function sum(a: number, b: number): number {
  return a + b;
}

Результат трансформации:

function sum(a, b) {
  return a + b;
}

Удаляются:

  • аннотации параметров;
  • возвращаемые типы;
  • интерфейсы и типы;
  • generics.

При этом сохраняется только исполняемый JavaScript-код.

Поддержка интерфейсов и типов

TypeScript-конструкции, которые полностью исчезают:

interface User {
  id: number;
  name: string;
}

type ID = string | number;

После компиляции:

Такие конструкции не имеют runtime-представления и полностью удаляются.

Enum и особенности трансформации

enum обрабатывается иначе, поскольку имеет runtime-значение:

enum Status {
  Active,
  Disabled
}

Результат:

var Status;
(function (Status) {
  Status[Status["Active"] = 0] = "Active";
  Status[Status["Disabled"] = 1] = "Disabled";
})(Status || (Status = {}));

При этом:

  • числовые enum полностью эмитятся;
  • string enum сохраняет строки;
  • const enum может инлайниться или требовать особой настройки (в зависимости от конфигурации и версии SWC).

JSX и TSX в SWC

SWC объединяет поддержку TypeScript и JSX через TSX-парсер.

const App = (): JSX.Element => {
  return <div>Hello</div>;
};

Трансформация:

const App = () => {
  return React.createElement("div", null, "Hello");
};

или при automatic runtime:

import { jsx as _jsx } from "react/jsx-runtime";

const App = () => {
  return _jsx("div", { children: "Hello" });
};

Поддерживаются:

  • React automatic runtime;
  • classic runtime;
  • TypeScript JSX namespace inference.

Ограничения TypeScript в SWC

SWC не является TypeScript-компилятором в полном смысле, поэтому отсутствуют следующие возможности:

  • проверка типов (type-checking полностью отсутствует);
  • генерация .d.ts файлов;
  • строгое соблюдение tsconfig.json правил компиляции;
  • часть семантических проверок (например, контроль совместимости типов);
  • диагностика ошибок типов.

Это означает, что код может быть синтаксически корректным, но семантически ошибочным без каких-либо предупреждений.

tsconfig.json и его роль

SWC не использует tsconfig.json как основной источник конфигурации компиляции. Однако некоторые параметры могут быть частично сопоставлены вручную:

  • target → jsc.target;
  • module → module.type;
  • JSX → jsc.transform.react;
  • strict options → игнорируются.

Пример несоответствия:

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true
  }
}

Эти параметры не влияют на SWC-трансформацию, поскольку не относятся к синтаксическому уровню.

TypeScript в сборщиках через SWC

Next.js

SWC используется как основной трансформер TypeScript-кода вместо Babel:

  • ускоренная компиляция;
  • встроенная поддержка TS и TSX;
  • отсутствие отдельного Babel-пайплайна.

Type checking выполняется отдельно через tsc –noEmit.

Vite (через плагин)

В связке с Vite SWC применяется для ускоренного трансформирования:

  • быстрый dev-server;
  • минимизация задержек при HMR;
  • делегирование проверки типов внешним инструментам.

Webpack (swc-loader)

Через swc-loader:

module.exports = {
  test: /\.[jt]sx?$/,
  use: {
    loader: "swc-loader",
    options: {
      jsc: {
        parser: {
          syntax: "typescript",
          tsx: true
        }
      }
    }
  }
};

SWC заменяет ts-loader или babel-loader в части трансформации.

Generics и их обработка

Generics в TypeScript полностью исчезают после компиляции:

function identity<T>(value: T): T {
  return value;
}

Результат:

function identity(value) {
  return value;
}

Типовая параметризация не влияет на runtime-код.

Namespaces и legacy-синтаксис

Поддержка namespace присутствует, но рассматривается как устаревшая модель:

namespace Utils {
  export function log(msg: string) {
    console.log(msg);
  }
}

Результат:

var Utils;
(function (Utils) {
  function log(msg) {
    console.log(msg);
  }
  Utils.log = log;
})(Utils || (Utils = {}));

Decorators

Поддержка декораторов зависит от включения соответствующего флага:

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "decorators": true
    }
  }
}

Пример:

function readonly(target: any, key: string) {}

class Test {
  @readonly
  method() {}
}

После трансформации формируется обёртка с вызовом декоратора в runtime.

Важно учитывать различие между legacy decorators и stage-3 decorators, которые могут иметь разное поведение в зависимости от версии SWC.

Type-only imports

TypeScript-конструкции вида:

import type { User } from "./types";

полностью удаляются:

Обычные импорты сохраняются без изменений.

Производительность трансформации TypeScript

SWC оптимизирован для высокоскоростной обработки TS-кода:

  • Rust-реализация снижает накладные расходы GC;
  • параллельная обработка файлов;
  • отсутствие анализа типов уменьшает время компиляции;
  • кэширование AST на уровне сборщиков.

В типичных проектах разница с tsc и Babel становится заметной при больших кодовых базах, особенно при активном HMR.

Отличия SWC от tsc в контексте TypeScript

  • SWC: синтаксическая трансформация TypeScript → JavaScript
  • tsc: семантическая проверка + генерация JavaScript + деклараций

Ключевая граница ответственности:

  • SWC работает только с синтаксисом;
  • TypeScript Compiler работает с типовой системой.

Это разделение делает их часто используемыми совместно:

  • SWC — сборка;
  • tsc — проверка типов.