В этом уроке вы узнаете о выводе типов в TypeScript. Вывод типа описывает, где и как TypeScript выводит типы, если вы не аннотируете их явно.
Вывод базового типа
Когда вы объявляете переменную, вы можете использовать аннотацию типа, чтобы явно указать для нее тип. Например:
let counter: number;
Однако, если вы инициализируете переменную counter
числом, TypeScript выведет тип counter
как number
. Например:
let counter = 0;
Это эквивалентно следующему утверждению:
let counter: number = 0;
Аналогичным образом, когда вы присваиваете параметру функции значение, TypeScript определяет тип параметра в соответствии с типом значения по умолчанию. Например:
function setCounter(max=100) { // ... }
В этом примере TypeScript определяет тип параметра max
как number
.
Точно так же TypeScript выводит следующий тип возвращаемого значения функции increment()
как number
:
function increment(counter: number) { return counter++; }
Это то же самое, что:
function increment(counter: number) : number { return counter++; }
Лучший алгоритм общего типа
Рассмотрим следующее задание:
let items = [1, 2, 3, null];
Чтобы вывести тип переменной items
, TypeScript должен учитывать тип каждого элемента в массиве.
Он использует алгоритм наилучшего общего типа для анализа каждого типа-кандидата и выбора типа, совместимого со всеми другими кандидатами.
В этом случае TypeScript выбирает тип числового массива ( number[]
) как наиболее распространенный тип.
Если вы добавите строку в массив items
, TypeScript определит тип элементов как массив чисел и строк: (number | string)[]
let items = [0, 1, null, 'Hi'];
Когда TypeScript не может найти наилучший общий тип, он возвращает тип массива объединения. Например:
let arr = [new Date(), new RegExp('d+')];
В этом примере TypeScript определяет тип arr
как (RegExp | Date)[]
.
Контекстная типизация
TypeScript использует расположение переменных для определения их типов. Этот механизм известен как контекстная типизация. Например:
document.addEventListener('click', function (event) { console.log(event.button); // });
В этом примере TypeScript знает, что параметр event
является экземпляром MouseEvent
из-за события click
.
Однако, когда вы измените событие click
на событие scroll
, TypeScript выдаст ошибку:
document.addEventListener('scroll', function (event) { console.log(event.button); // compiler error });
Ошибка:
Property 'button' does not exist on type 'Event'.(2339)
TypeScript знает, что event
в данном случае является экземпляром UIEvent
, а не MouseEvent
. А UIEvent
не имеет свойства button
, поэтому TypeScript выдает ошибку.
Вы найдете контекстную типизацию во многих случаях, таких как аргументы вызовов функций, утверждения типов, члены объектов и литералы массивов, операторы возврата и правые части присваиваний.
Сравнение вывод типа и аннотации типа
Ниже показано различие между выводом типа и аннотациями типов:
Вывод типа | Аннотации типов |
TypeScript угадывает тип | Вы явно указываете TypeScript тип |
Итак, когда вы используете вывод типов и аннотации типов?
На практике всегда следует максимально использовать вывод типа. Вы используете аннотацию типа в следующих случаях:
- Когда вы объявляете переменную и позже присваиваете ей значение.
- Когда вам нужна переменная, которую нельзя вывести.
- Когда функция возвращает тип
any
и вам нужно уточнить значение.
Заключение
- Вывод типа происходит, когда вы инициализируете переменные, устанавливаете значения параметров по умолчанию и определяете типы возвращаемых функций.
- TypeScript использует алгоритм наилучшего общего типа для выбора типов-кандидатов, совместимых со всеми переменными.
- TypeScript также использует контекстную типизацию для вывода типов переменных на основе расположения переменных.