Перейти к содержимому
Теория · Простые и особые типы · урок 1 из 8

Примитивные типы

Чему вы научитесь

Чему вы научитесь:

  • записывать примитивные типы number, string, boolean, bigint и symbol;
  • объяснять, почему в строгом режиме null не подходит к типу string;
  • отличать any от unknown и проверять значение unknown перед использованием;
  • объяснять, что значат void и never в типе результата функции.
Посылка any проходит мимо стола досмотра, а запечатанную коробку unknown вскрыли и нашли внутри string

Вернёмся на таможню из первой темы. Каждая посылка едет с декларацией, где написано, что лежит внутри. Инспектор сверяет декларацию с содержимым и только потом пропускает посылку через границу. В TypeScript декларация — это тип, а инспектор — компилятор tsc.

Самые простые посылки везут одно значение: число, кусок текста, ответ «да» или «нет». Типы таких значений называются примитивными. Сами значения вам знакомы по JavaScript, а TypeScript добавляет к ним декларацию:

TypeScript
const price: number = 199.9;
const title: string = "Kettle";
const inStock: boolean = true;
console.log(title, price, inStock); // Kettle 199.9 true

Разберём пример по строкам:

  1. price объявлена с типом number: в ней число.
  2. title хранит строку, её тип — string.
  3. inStock хранит логическое значение, её тип — boolean.
  4. console.log печатает все три значения. Типы на вывод не влияют: после проверки tsc их стирает.

Если положить в коробку не то, что написано в декларации, например строку "yes" в inStock, инспектор остановит посылку ещё до запуска программы.

Пять примитивных типов

В аннотациях пишут те же слова, которые возвращает оператор typeof в JavaScript:

  • number — любые числа: целые, дробные, а ещё NaN и Infinity;
  • string — строки;
  • boolean — два значения, true и false;
  • bigint — целые числа любой длины, их пишут с буквой n на конце: 10n;
  • symbol — уникальные значения, которые создаёт функция Symbol.

Два последних типа встречаются в программах редко, но записываются так же:

TypeScript
const big: bigint = 9007199254740993n;
const id: symbol = Symbol("id");
console.log(typeof big, typeof id); // bigint symbol

typeof печатает те же слова, что стоят в аннотациях: bigint и symbol. Смешивать bigint и number в одном выражении нельзя. Выражение big + 1 компилятор не пропустит, а JavaScript на такой строке бросил бы TypeError.

number хранит целые числа точно только до 9007199254740991, а число из примера больше: как number оно округлилось бы до 9007199254740992. Для таких чисел и нужен bigint.

Один number для всех чисел

Во многих языках целые и дробные числа — разные типы: int, float, double. В TypeScript, как и в JavaScript, для всех обычных чисел один тип — number. Переменная let count: number = 3 спокойно примет и 2.5.

Типа int в TypeScript нет вовсе. Аннотация let count: int = 3 даёт ошибку Cannot find name 'int': компилятор не знает такого имени.

На собеседовании часто спрашивают, какие базовые типы есть в TypeScript. В ответе стоит назвать пять примитивов, сказать, что number один на все числа, и добавить про null и undefined. О них — следующий раздел.

null и undefined — отдельные типы

В JavaScript пустое значение можно положить в любую переменную. Беда приходит позже: если в city лежит null, строка city.toUpperCase() останавливает программу с TypeError: Cannot read properties of null (reading 'toUpperCase').

В строгом режиме, который в курсе включён всегда, у null и undefined свои типы — тоже примитивные, так что всего примитивных типов семь. В типе null одно значение — null, в типе undefined тоже одно — undefined. К другим типам они не подходят:

TypeScript
const city: string = null; // ✗
TEXT
error TS2322: Type 'null' is not assignable to type 'string'.

Декларация «текст» на пустой коробке — неправда, и инспектор такую посылку не пропускает. Так же let count: number = undefined даёт Type 'undefined' is not assignable to type 'number'. Зато переменной типа string можно доверять: в ней всегда строка, и её методы не упадут на null.

Учтите: typeof null по старой ошибке JavaScript даёт "object", а тип в TypeScript называется null.

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

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

Тип написали с большой буквы:

TypeScript
function shout(text: string): string {
    return text.toUpperCase();
}
const greeting: String = "Hi";
console.log(shout(greeting)); // ✗
TEXT
error TS2345: Argument of type 'String' is not assignable to parameter of type 'string'.
  'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.

String, Number и Boolean с большой буквы — типы объектов-обёрток: так называют объекты, которые JavaScript создаёт вызовом вроде new String("Hi"). TypeScript разрешает писать такие типы, но там, где ждут string, они не подходят. Вторая строка сообщения подсказывает исправление: напишите string строчными буквами, и вызов shout(greeting) пройдёт проверку.

Главное

  • Примитивные типы пишут строчными буквами: number, string, boolean, bigint, symbol — теми же словами, что печатает typeof.
  • number — один тип для целых и дробных чисел; типов int и float в TypeScript нет.
  • В строгом режиме null и undefined — отдельные типы, и string их не принимает.
  • String, Number и Boolean с большой буквы — типы объектов-обёрток, в аннотациях их не пишут.