# Простые типы

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

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

```typescript
const a: number = 10;
```

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

```javascript
const a = 10;
```

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

```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`)

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

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

## Массивы

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

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

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

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

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

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

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

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

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

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

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

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

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

```typescript
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)

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

```typescript
const a: [number] = [1];
```

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

```typescript
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)
*/
```

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

```typescript
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` можно присваивать переменным любого типа.

```typescript
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`. Таким переменным можно присваивать только два этих типа (почти, но об это в следующей серии).

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

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

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

В TypeScript любой [литерал](https://ru.wikipedia.org/wiki/%D0%9B%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D0%BB_\(%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0\)) имеет тип. Например

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

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

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

```typescript
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[]`. Если мы хотим, чтобы переменная слева была кортежем - нужно явно указывать тип.

```typescript
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 действительно умеет выводить типы. Некорректность заключается в том, что типы некоторых выражений указаны не совсем точно. Почему они не совсем точные и какие типы должны быть на самом деле, а также почему любому числовому массиву соответствует любой корте из чисел, но не наоборот - поговорим об этом в следующей части.

## Задания

* [Задание #1](https://www.typescriptlang.org/play?strictNullChecks=false\&ts=4.1.3#code/PQKgsAUABDWMQgguEEAwgg2EEBwgghEEKwgVDsIIXhAlBxEC3zUHkQAGiiI0D4QQRhBBpECnx2cG4QOqOwCRA0GdBFAR1APCCB+EDQdygMRA0aSCGCQAxgHsAdgGcALlACGARgBcUTQFcAtgCMApgCcoAXjVa9hgExmb69QBs7A00XKDcdfQMAZjM9BwBLTQBzUPCPAwAWM0tbRwBtAF1UiA0IwwBWMwBBBwcDAE8AHjjEpIA+YtL0gDYzPJbkoucwkvdIgHY+3wCgzWoc+wchka7IgA4+hfyC6hq6poH25bTIowAGTetF6jytpZvbq8cdqDzH3KWCr+LIUEhYeDIdDYKAYNASJjUWiMFhsKCcbh8ARCETiKQyeSKCDKE5QGymGDDcZnADcuJs3kJUAAZgZ-No7GTRmUbDEqQAifx0gwAawM7KZqzxWSpeV0DgsdmotPpdgKgrGeN6ovO1HZ53Z8vJk1FADp9WKJXKtcyPDYNqK3vrdXlzl8XlaDeqzpr7ZBcaoABZ2VQ8nx+QLBUI2DJ5KIm37gaCwQB4IAxyIAmEEwOAkWEAAiBYMSkfBMHCqIwAWlUGSh9GYrHYTC4PH4gmEokk0jkCn+sATUEAsiD0MTwrgIHBoXtCHCAQRAoBI03QE+nkGIsTiIO7F8vQFBAIggffHk+nk+EC6FXp9PIA+gS7qF81AANRQcoKsqH33HzwXzy67QWGxxAAUZwAlPeHiPiebLTIGITDKoUR5GcJoHt6T4ZBe0FGEUN53h6CEnuUF4ZLqAAOFjaJ636ctyfLsgBQA)

* [Задание #2](https://www.typescriptlang.org/play?strictNullChecks=false#code/PQKgsAUABDWOgggGEECwgDBCIIVhAqsBwgh+EG4OwgCgYiDaByIFNlAYLwgCg4iDo3aDyIFEoNwgbAhgDRQAjfgGNKUACb9UCQFwg-eqkB8IIEYQQNIgkWFBqY1HRVEWAJEGzLFMqDMWAeEHxdS2AHSQQwSJGEB7AHYBnAC5Q3FAAvFAAZtwANj4ApgDc7t7+giHhUbEJEJ6+AaKhEdHxiTkSqQUZbhDFyQCOAIyp3JnZtQBMqeIA2gAMALrNSQE1AMypNe0A1FD1UFPiDpExXgDmfgAWAyU1ACypAgtLq2uzgp2tvQcr65u1AKx7IcGhwp11vT391UMAbKkvbx9Hs9Xu8+h8bkMAOxjX5PUI1e5wqD-d5vCHTAAcAC4oF4AK6RSJ-cFAA)

* [Пример решения задания #1](https://www.typescriptlang.org/play?strictNullChecks=false\&ts=4.1.3#code/PQKgsAUABDWMQgguEEAwgg2EEBwgVDsIIXhAmHEQQVhBs1B5EABoo9AhEED4QQRhBBpECmwKkcG4QGqGwCRA06aCKAhqAeEED8IGnYlAYiBo0kEMEgBjAPYA7AM4AXKAEMAjAC4oGgK4BbAEYBTAE5QAvFEMAGANyrNugwCZTazU1ABtbfQ1nKB17c1svCHVtPX0AZlNdewBLDQBzKIAiEP1igGt9AoSk330AFlMLGwcAbQBdKOb3VqqfFIBWUwBBe3t9AE8AHkyc3IA+DqKS-XKC7u9kgwA2U2bpvPaXZsWyirXE3oMAdh2g0PCNCka7ewOoZpi4ii6ejf0ADh2TxarQow1Gkz2c1ezU6bhBb2Oy1OZ2qKXcgKszwozSBL2xOMxDnhMNxrTJ0Pc2K6+Opb1h5LOkFAkFg8GQ6CgVDQ4gYFGo9CYLDYDE43D4AiEIgkUlk8kUynOG2sJjMhMcLkunnWvmsASgtzCESiADMSlp4tq9NZ0lBIYViidKpb9fV9cFDRo2h0PrYKKaQuaURdrNs3riKJCKW4KAV3Ksfjrrm67hEvYcAHSZ96xWxkhNWgF03FtYmQkvQmGZ9P0sn4qtHOMMyDOlQAC1sKlKgXd9yi1lqzVSjIgzOgsEAeCB0EiAJhA0FRWOICIABEAIoiI2AYBD5tEYzFYHC4vH4gmEYkk0jkCjHMGnUEAsiC0URsTgIVgYOgv1iAQRAoOIlzRp2XZBRCvJQW0MKJ3HzKAVD8e0lhWaCVBtZoDXuR41WhH0vjhJDXTLaECksBDTgSUAoEARBAX1-f9AP-IQwMVXw2w7UoAH0VVxKIVAggBqKA+iQ9tOzYuCXFg9MtHMaxMgACjcABKITWLYm00KNcTUmaXCW2E9jam4rTDHafjBN0lS+m42p0wAB3MLRW1kxEViUoA)

* [Пример решения задания #2](https://www.typescriptlang.org/play/?strictNullChecks=false#code/PQKgsAUABDWOgggGEECwgDCcIFQQiCA4QQ-CBcOwgCgYiBaByIFFlPoLwgCg4iCCsINVoPIgUSg3CBsCGANFACN+AYwpQAJvwwJAXCD86GQHwggRhBA0iCRYUagyhqOiqIsASIFmWKZUGYsA8IHi4ksAOkghgkSMID2AOwDOAFyhuKABeKABGAAYAbg8fAMEALigAgCcAS28Ac1CoACIARwB3AFM8uL9A4WSAbW8AVwAbRv4atMys-gFPT0aS7m8AXUHcuqaWqBq8vP4AM25G3xLh2IgvSolahoBbARLUkbCaqMHV9zX4wILw3O5V9YSCgCZc8RrI04rHgGZc56gANRQa6AiSOPrZfwAC3ul2BABZcgJwSVIVDQQIak9Bii0bCNgUAKxI0IhMLCY6Dd6fC4EgBsuQp4SpH1J5Mp1Op+MeAHY-gyyWEiWyoEyqczuVcABzJBrNRlcoA)
