Перейти к содержимому
Теория · Аннотации и вывод типов · урок 2 из 9

Вывод типов

В прошлом уроке вы подписывали каждую банку сами. Но часто содержимое видно и без наклейки. Если в банку насыпали гречку, подписать её может помощник: он видит, что внутри, и пишет «Гречка» за вас.

В TypeScript такой помощник — компилятор. Запись let count: number = 0 говорит «число» дважды: один раз в аннотации и второй раз нулём справа. Компилятору хватает нуля. Когда компилятор сам определяет тип по коду — по начальному значению переменной или по тому, что возвращает функция, — это называется выводом типов.

Тип из начального значения

TypeScript
let count = 0;
let title = "Отчёт";
count = count + 1;
title = title + " за май";
console.log(count, title); // 1 Отчёт за май

Аннотаций здесь нет, но типы у переменных есть. Давайте разберём пример по строкам:

  1. let count = 0; — справа число, и TypeScript выводит для count тип number.
  2. let title = "Отчёт"; — справа строка, и title получает тип string.
  3. count = count + 1; кладёт число в number — проверка проходит.
  4. title = title + " за май"; кладёт строку в string — тоже проходит.
  5. console.log печатает 1 Отчёт за май.

Выведенный тип проверяется так же строго, как написанный. Строка count = "два"; дала бы здесь ту же ошибку TS2322, что и с аннотацией let count: number = 0.

Как увидеть выведенный тип

Помощник пишет наклейку, но в коде её не видно. Чтобы её прочитать, наведите курсор на имя в редакторе — в VS Code или в TypeScript Playground. Над count появится подсказка let count: number, над title — let title: string.

Подсказкой удобно проверять себя. Прежде чем гадать, какой тип у переменной, наведите на неё курсор: подсказка покажет то, что знает компилятор.

Тип результата функции

Помощник читает не только начальные значения, но и return:

TypeScript
function withDelivery(price: number) {
    return price + 300;
}

const total = withDelivery(1200);
console.log(total); // 1500

У функции нет аннотации ): number, но TypeScript видит выражение после return: price + 300 — это число плюс число, значит, результат тоже число. Поэтому и total получает тип number.

Тип параметра price здесь написан явно. У параметра без значения по умолчанию нет начального значения, и помощнику нечего прочитать.

Переменная без значения

Иногда переменную объявляют без начального значения, а заполняют позже:

TypeScript
let total;
total = 1200;
total = "бесплатно";
console.log(total); // бесплатно

Здесь читать нечего, и подсказка над total в первой строке покажет let total: any. any — особый тип «что угодно»: в такую переменную можно записать и число, и строку, и tsc промолчит.

Наклейки на такой банке нет: помощник только запоминает, что в неё насыпали последним. Поэтому над total в строке с console.log подсказка покажет let total: string, а записать в total по-прежнему можно что угодно.

Если переменной нужен тип, напишите его сами: с объявлением let total: number; строка total = "бесплатно"; даст ошибку TS2322.

Что такое вывод типов, часто спрашивают на собеседовании. Короткий ответ: компилятор определяет тип по начальному значению переменной и по return функции. Там, где читать нечего, тип пишут сами.

Частая ошибка

Ждать, что тип меняется вместе со значением, как в JavaScript:

TypeScript
let price = 1200;
price = "бесплатно"; // ✗
TEXT
error TS2322: Type 'string' is not assignable to type 'number'.

TypeScript вывел тип price один раз — из начального значения 1200, — и дальше этот тип не меняется. Текст для такой цены хранят в отдельной переменной, например let priceLabel = "бесплатно";.

Главное

  • Вывод типов: TypeScript сам определяет тип переменной по начальному значению — let count = 0 получает number.
  • Выведенный тип проверяется так же строго, как аннотация, и после объявления не меняется.
  • Тип результата функции выводится из выражения после return.
  • У переменной без значения тип any, поэтому тип такой переменной пишут сами: let total: number;.