Типы исчезают при компиляции
На таможне декларации нужны только на границе. Когда посылки проверены, бумаги выбрасывают, и внутри страны их больше никто не читает. tsc поступает так же: сначала проверяет типы, а потом пишет JavaScript, в котором их нет. Это называется стиранием типов.
Посмотрим, что tsc оставит от файла hello.ts с аннотациями. Нажимайте «Следующий шаг» и следите, во что превращается каждая подсвеченная строка TypeScript.
У параметра и у результата были аннотации : string — в JavaScript их нет, а функция осталась.
Что осталось в hello.js
После компиляции в hello.js:
- исчезли все аннотации:
: stringу параметра и результата,: stringи: numberу переменных; - осталось всё, что выполняется: функция, шаблонная строка, значения
"Anna"и3, вызовconsole.log; - в начале появилась строка
"use strict";— её дописалtsc. Это строгий режим самого JavaScript, а неtsc: к типам он отношения не имеет.
Получился обычный JavaScript, в котором нет ни слова о типах. Команда node hello.js выполнит его так же, как любой другой файл .js.
Зачем стирать типы
Почему бы не оставить аннотации в JavaScript? Потому что это не JavaScript. Встретив : string в файле .js, браузер или Node.js остановятся с синтаксической ошибкой ещё до первой строки. Поэтому tsc и вырезает типы: без них файл понятен и браузеру, и Node.js.
При запуске типов нет
Раз в hello.js типов нет, во время работы программы их никто не проверяет. Проверка была одна — до запуска, по тексту программы. Поэтому типы не защищают от данных, которые появляются только во время работы:
- текста, который пользователь ввёл в форму;
- ответа сервера;
- содержимого файла.
В картинке с таможней такие данные попадают в страну в обход границы, без декларации: tsc их никогда не видел. Если значение нужно проверить, программа делает это сама, средствами JavaScript, например через typeof.
На собеседовании часто спрашивают, существуют ли типы TypeScript во время выполнения. Нет: tsc стирает их при компиляции, и в работающей программе остаётся только JavaScript.
Ошибка не мешает записать файл
Здесь картинка с таможней перестаёт работать. Настоящий таможенник задержит посылку с неверной декларацией, а tsc сообщает об ошибке и всё равно записывает .js. Проверка типов и запись JavaScript — две отдельные работы, и вторая не ждёт успеха первой.
Чтобы tsc не записывал файл, пока в коде есть ошибки, нужен флаг --noEmitOnError:
$ tsc --noEmitOnError hello.tsС ним при ошибке новый hello.js не появится. Старый, если он остался от прошлой компиляции, при этом не изменится.
Частая ошибка
Увидеть сообщение tsc, но всё равно запустить hello.js. Вернёмся к функции из первого урока темы:
function formatPrice(price: number): string {
return price.toFixed(2);
}
console.log(formatPrice(100));
console.log(formatPrice("100")); // ✗error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.tsc hello.ts сообщит об этой ошибке, но hello.js всё равно запишет. Команда node hello.js напечатает 100.00, а на втором вызове программа остановится:
TypeError: price.toFixed is not a functionТипы стёрты, и строка "100" дошла до toFixed, как в JavaScript без всякого TypeScript. Исправление — сначала убрать ошибки, о которых сообщил tsc, и только потом запускать программу.
Главное
tscсначала проверяет типы, а потом пишет JavaScript без них: это стирание типов.- В
hello.jsнет аннотаций, поэтому при запуске типы ничего не проверяют. - Данные, которые приходят во время работы,
tscне видел: их проверяют средствами JavaScript, напримерtypeof. tscзаписывает.jsдаже при ошибках, а флаг--noEmitOnErrorэто запрещает.