Learning Book

Как работает компилятор tsc

Что делает tsc

Компилятор tsc выполняет две задачи:

  1. Проверяет типы — находит ошибки до запуска
  2. Генерирует JavaScript — удаляет типы и (опционально) понижает версию синтаксиса

Это два независимых процесса. Ошибки типов не мешают генерации JS по умолчанию.

Стирание типов (Type Erasure)

Типы существуют только на этапе компиляции. После компиляции они полностью удаляются:

// До компиляции (TypeScript)
function greet(person: string, date: Date) {
  console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}
// После компиляции (JavaScript)
function greet(person, date) {
  console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}

Аннотации : string и : Date исчезли. Браузеры и Node.js не знают о них — TypeScript-специфичный синтаксис стирается без следа.

Ключевое правило: аннотации типов никогда не влияют на поведение программы в рантайме.

Даунлевелинг (Downleveling)

Кроме стирания типов, tsc может понизить версию синтаксиса — переписать новый JavaScript в более старый.

По умолчанию TypeScript компилирует в ES5. Шаблонные строки превращаются в конкатенацию:

// Исходный код
`Hello ${person}, today is ${date.toDateString()}!`;
// Скомпилированный код (target: ES5)
"Hello ".concat(person, ", today is ").concat(date.toDateString(), "!");

Если указать более современный target:

tsc --target es2015 hello.ts

То шаблонные строки останутся как есть:

// target: ES2015+
`Hello ${person}, today is ${date.toDateString()}!`;

Большинство современных браузеров поддерживают ES2015+. Если не нужна совместимость с IE, смело ставьте es2015 или выше.

Компиляция при наличии ошибок

По умолчанию tsc генерирует JS даже если есть ошибки типов:

function greet(person, date) {
  console.log(`Hello ${person}, today is ${date}!`);
}

greet("Brendan");
// Ошибка: Expected 2 arguments, but got 1

Несмотря на ошибку, hello.js будет создан. Это сделано по замыслу: TypeScript не хочет вам мешать. Вы можете знать лучше, чем компилятор.

Это особенно полезно при миграции с JavaScript — код уже работает, а ошибки типов вы исправите постепенно.

Запрет генерации при ошибках

Если хотите строгое поведение — используйте флаг noEmitOnError:

tsc --noEmitOnError hello.ts

Теперь hello.js не обновится, пока все ошибки не будут исправлены.

Явные типы vs вывод типов

TypeScript часто определяет типы автоматически:

let msg = "hello there!";
// TypeScript определил: string — аннотация не нужна

Правило: не добавляйте аннотации, если TypeScript и так определяет тип правильно. Аннотации нужны, когда:

  • TypeScript не может определить тип (параметры функции)
  • Вы хотите указать более узкий или широкий тип
  • Тип неочевиден читателю кода
// Аннотация нужна — параметры не имеют контекста
function greet(person: string, date: Date) {
  console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}

// Аннотация не нужна — тип очевиден
const count = 42;

Обзор флагов tsc

ФлагНазначение
--targetВерсия JS на выходе (es5, es2015, es2020, esnext)
--noEmitOnErrorНе генерировать JS при ошибках
--outDirПапка для выходных файлов
--watchПерекомпиляция при изменении файлов
--strictВключить все строгие проверки

Подробнее о всех флагах — в главе про tsconfig.json.

Итоги

.ts → tsc → .js
         ↓
    1. Проверка типов (ошибки в консоли)
    2. Стирание типов (: string → ничего)
    3. Даунлевелинг (template → concat, если target < ES2015)
  • Типы существуют только на этапе компиляции и полностью стираются
  • По умолчанию JS генерируется даже при ошибках типов
  • --noEmitOnError запрещает генерацию при ошибках
  • --target управляет версией выходного JavaScript