Table of Contents #
Введение #
В этой главе обсуждается выведение типов в TypeScript. А именно, мы расскажем, где и как выводятся типы.
Основы #
В TypeScript существует несколько мест, где используется выведение типов для того, чтобы получить информацию о типах без явного ее указания. К примеру, в этом коде
let x = 3;
Тип переменной x
выводится в number
. Выведение такого рода происходит при инициализации переменных и членов, присваивании параметрам значений по умолчанию и определении типа возвращаемого значения функции.
В большинстве случаев выведение типов довольно прямолинейно. В последующих разделах мы опишем несколько тонкостей этого процесса.
Наилучший общий тип #
Когда выведение делается на основании нескольких выражений, их типы используются для нахождения "наилучшего общего типа". К примеру,
let x = [0, 1, null];
Чтобы вывести тип x
в этом случае, нужно проверить тип каждого элемента в массиве. В данном случае есть два варианта для типа массива: number
и null
. Алгоритм нахождения наилучшего общего типа проверяет каждый тип-кандидат, и выбирает тот, который совместим со всеми остальными.
Поскольку наилучший общий тип должен быть выбран из предоставленных типов, бывают случаи, когда типы имеют общую для всех структуру, но ни один из них не является базовым для всех остальных. К примеру:
// Здесь Rhino — носорог, Elephant — слон, а Snake — змея let zoo = [new Rhino(), new Elephant(), new Snake()];
В идеале, хотелось бы, чтобы тип zoo был выведен как Animal[]
(то есть массив объектов класса Animal
— животное). Но, так как в массиве нет ни одного объекта, который бы имел класс именно Animal
, компилятор не способен получить такой результат. Чтобы исправить это, придется явно указать тип, если ни один объект не имеет тип, базовый для всех остальных:
let zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()];
Если компилятору не удается найти наилучший общий тип, результатом выведения будет тип пустого объекта, то есть {}
. Так как у такого типа нет членов, попытка использовать какие-либо его свойства приведет к ошибке. В результате такого выведения по-прежнему можно использовать объект, словно его тип неизвестен, и гарантировать безопасность типов в тех случаях, когда тип объекта не может быть найден неявно.
Контекстный тип #
В некоторых случаях выведение типов работает и в "другом направлении". Это называется "контекстной типизацией". Контекстная типизация происходит, когда о типе выражения можно сделать догадку на основании его положения. К примеру:
window.onmousedown = function(mouseEvent) { console.log(mouseEvent.buton); //<- Ошибка };
Для того, чтобы найти ошибку типов в этом примере, компилятор сначала использовал тип функции Window.onmousedown
, чтобы вывести тип функционального выражения из правой части присваивания. После этого он смог вывести тип параметра mouseEvent
. Если бы данное функциональное выражение находилось там, где его тип нельзя было бы вывести из контекста, тип параметра mouseEvent
был бы any
, и компилятор не выдал бы ошибки.
Если выражение, тип которого был выведен из контекста, содержит явное указание типа, то выведенный контекстный тип игнорируется. То есть, если бы предыдущий пример был записан как:
window.onmousedown = function(mouseEvent: any) { console.log(mouseEvent.buton); //<- Теперь ошибка не выдается };
Явно указанный тип параметра в функциональном выражении будет иметь приоритет над контекстным типом. По этой причине компилятор не выдаст ошибки, поскольку контекстный тип не применяется.
Контекстная типизация применяется во многих случаях. Как правило, это аргументы при вызове функций, правая часть присваивания, проверки типов, члены объектов и литералы массивов, а также инструкции return
. Также контекстный тип используется в качестве кандидата в наилучший общий тип. К примеру:
function createZoo(): Animal[] { return [new Rhino(), new Elephant(), new Snake()]; }
Здесь есть четыре кандидата на роль наилучшего общего типа: Animal
, Rhino
, Elephant
и Snake
. Алгоритм поиска наилучшего общего типа способен выбрать из них Animal
.
Поддержите перевод документации:
Documentation generated by mdoc.