Простые типы

Объявление переменной с определенным типом

Начнем изучение TypeScript с самых простых конструкций. Если вы хотите объявить переменную, в которую можно будет записать любое число (но при этом только число), вам нужно воспользоваться встроенным типом number. Это будет выглядеть следующим образом:

const a: number = 10;

Это очень похоже на то, как объявляется переменная в JavaScript:

const a = 10;

Только добавляется описание типа переменной. Делается это при помощи двоеточия (:) и названия типа (number). Если попытаться присвоить переменной с типом number значение другого типа (например, строки), TypeScript выдаст ошибку во время компиляции:

const a: number = "it's a string"; //Error: Type '"it's a string"' is not assignable to type 'number'.(2322)

number, string и boolean

Рассмотри следующие два примитивных типа: 1. string - позволяет присваивать любую строку 2. boolean - позволяет присваивать любое логическое значение (true или false)

const a: number = 10;
const b: string = "it's a string";
const c: boolean = true;

По аналогии с примером для number, если мы попытаемся присвоить значение, которое не совместимо с типом, компилятор TypeScript выдаст ошибку.

Массивы

Существует несколько способов, как указать на то, что мы хотим записывать в переменную массив каких-то значений. Первый способ -использовать постфикс [] после объявления типа элементов массива.

const a: number[] = [1, 2, 3];

Второй способ - использовать интерфейс Array и передать ему в качестве generic-параметра тип элементов.

const a: Array<number> = [1, 2, 3];

Что такое интерфейс и generic-параметры мы рассмотрим позже. Сейчас важно понимать, что тип для массива можно объявить двумя разными способами и что эти два способа эквивалентны.

const a: number[] = [1, 2, 3];
const b: Array<number> = a; //Ошибок нет

Мы в основном будем пользоваться первым способом.

Все описанные правила для массива применимы не только для number, но и для других типов (например, рассмотренные нами string и boolean).

const a: number[] = [1, 2, 3];
const b: string[] = ["1", "2", "3"];
const c: boolean[] = [true, true, false];

Рассмотрим несколько важных особенностей массивов:

  1. Если хотя бы один элемент присваиваемого массива не соответствует типу элементов массива, то TypeScript выдаст ошибку во время компиляции.

    const a: number[] = [1, 2, 3, "4"]; //Error: Type 'string' is not assignable to type 'number'.(2322)
  2. Присвоить пустой массив можно любому типу-массиву.

    const a: number[] = [];
    const b: string[] = [];
    const c: boolean[] = [];
  3. Тип-массив, помимо ограничений на типы элементов этого массива, также определят свойство length. Свойство length имеет тип number и хранит количество элементов в этом массиве.

let a: number = 10;
const b: number[] = [10];

console.log(b.length); //1 
console.log(a.length); //Error: Property 'length' does not exist on type 'number'.(2339)

a = b.length; 
const c: boolean = b.length; //Error: Type 'number' is not assignable to type 'boolean'.(2322)

Кортеж (Tuple)

Кортеж - это особый вид массива. Он позволяет строго задать количество элементов массива, а также тип каждого элемента. Например.

const a: [number] = [1];

В данном примере мы объявили переменную, которой можно присвоить массив только с одним элементом и тип этого элемента должен быть числом. Все следующие примеры содержат ошибку.

const a: [number] = []; //Error: Property '0' is missing in type '[]' but required in type '[number]'.(2741)
const b: [number] = ["123"]; //Error: Type 'string' is not assignable to type 'number'.(2322)
const c: [number] = [1, 2]; 
/* Error: 
Type '[number, number]' is not assignable to type '[number]'. 
    Types of property 'length' are incompatible.
        Type '2' is not assignable to type '1'.(2322)
*/

В кортеже можно указать типы для нескольких элементов. Причем типы элементов могут быть любые, включая массивы, вложенные кортежи и типы, которые мы рассмотрим далее.

const a: [number, number] = [1, 2];
const b: [string, boolean] = ["123", true];
const c: [number[]] = [[1,2,3]];
const e: [[string], [number, number], boolean[]]= [["1"], [100, 100], [true, true, false, true]];

null и undefined

Без дополнительных настроек значения null и undefined можно присваивать переменным любого типа.

const a: number = null;
const b: number = undefined;
const c: number[] = null;
const d: [string, string] = null;
const e: [string, string] = [null, null];

Однако, можно типизировать переменные типами null и undefined. Таким переменным можно присваивать только два этих типа (почти, но об это в следующей серии).

const a: null = null;
const b: undefined = undefined;

const c: null = 1; //Error: Type '1' is not assignable to type 'null'.(2322)

Автоматический вывод типов

В TypeScript любой литерал имеет тип. Например

10 // имеет тип number
"abav" // string
[1, 2, 3] // number[] а не кортеж [number, number, number]

TypeScript автоматически определят тип литерала. При использовании оператора присваивания (=) TypeScirpt проверяет соответствие типа правого и левого операнда. Если типы не совместимы, то возникает ошибка компиляции.

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

const a = 10; // a: number
const b = a; // b: number
const c = a + b; // c: number
const d = c - 2*a === 0; // d: boolean

У механизма автоматического вывода типов есть ряд особенностей. Одна из таких особенностей - различие между массивом и кортежем. Дело в том, что выражение [1, 2, 3] имеет тип number[], а не [number, number, number]. Соответственно автоматический вывод типов присвоит левой части тип number[]. Если мы хотим, чтобы переменная слева была кортежем - нужно явно указывать тип.

let a: [number, number];
const b = [1, 2];
a = b; // Error: Type 'number[]' is missing the following properties from type '[number, number]': 0, 1(2739)

const c: [number, number] = [1, 2];
a = c;

Однако обратная операция всегда выполнима - значение с типом [number, number] всегда можно присвоить в переменную с типом number[].

P.S.

В это части мы задели несколько примитивных концепций TypeScript. Однако некоторые вещи, описанные выше, не полностью раскрыты и даже слегка некорректны. Особенно это касается автоматического вывода типов. Нет, TypeScript действительно умеет выводить типы. Некорректность заключается в том, что типы некоторых выражений указаны не совсем точно. Почему они не совсем точные и какие типы должны быть на самом деле, а также почему любому числовому массиву соответствует любой корте из чисел, но не наоборот - поговорим об этом в следующей части.

Задания

Last updated