Как работает компилятор tsc
Что делает tsc
Компилятор tsc выполняет две задачи:
- Проверяет типы — находит ошибки до запуска
- Генерирует 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