Spec-Zone.ru › TypeScript 5.1

Тип вывода

В TypeScript есть несколько мест, где используется вывод типов для предоставления информации о типе, когда явного аннотирования типа нет. Например, в этом коде

let x = 3;

Тип переменной x выводится как number. Такой вывод происходит при инициализации переменных и членов, установлении значений параметров по умолчанию и определении типов возвращаемых значений функций.

В большинстве случаев вывод типов прост. В следующих разделах мы рассмотрим некоторые нюансы вывода типов.

Наилучший общий тип

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

let x = [0, 1, null];

Чтобы вывести тип x в приведённом выше примере, необходимо рассмотреть тип каждого элемента массива. Здесь у нас есть два варианта для типа массива: number и null. Алгоритм наилучшего общего типа рассматривает каждый кандидатный тип и выбирает тип, совместимый со всеми другими кандидатами.

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

let zoo = [new Rhino(), new Elephant(), new Snake()];

В идеале, мы хотели бы, чтобы zoo был выведен как Animal[], но так как в массиве нет объекта, строго соответствующего типу Animal, мы не делаем вывода о типе элемента массива. Чтобы исправить это, явно укажите тип, когда ни один тип не является супертипом всех остальных кандидатов:

let zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()];

Когда наилучший общий тип не найден, результат вывода — это тип массива-объединения (Rhino | Elephant | Snake)[].

Контекстный вывод типов

Вывод типов также работает в «обратном направлении» в некоторых случаях в TypeScript. Это известно как «контекстный вывод типов». Контекстный вывод типов происходит, когда тип выражения подразумевается его положением. Например:

window.onmousedown = function (mouseEvent) {
  console.log(mouseEvent.button);
  console.log(mouseEvent.kangaroo);
};

Здесь TypeScript-проверяющий типов использовал тип функции Window.onmousedown для вывода типа выражения функции в правой части присваивания. При этом он смог вывести тип параметра mouseEvent, который содержит свойство button, но не свойство kangaroo.

Это работает, потому что в типе window уже объявлен onmousedown:

// Declares there is a global variable called 'window'
declare var window: Window & typeof globalThis;

// Which is declared as (simplified):
interface Window extends GlobalEventHandlers {
  // ...
}

// Which defines a lot of known handler events
interface GlobalEventHandlers {
  onmousedown: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null;
  // ...
}

TypeScript достаточно умен, чтобы выводить типы и в других контекстах:

window.onscroll = function (uiEvent) {
  console.log(uiEvent.button);
};

Исходя из того, что вышеприведенная функция присваивается Window.onscroll, TypeScript знает, что uiEvent является UIEvent, а не MouseEvent, как в предыдущем примере. Объекты UIEvent не содержат свойства button, поэтому TypeScript выдаст ошибку.

Если бы эта функция не находилась в контексте, где требуется вывод типов, аргумент функции неявно имел бы тип any, и никакая ошибка не была бы выдана (если вы не используете опцию noImplicitAny):

const handler = function (uiEvent) {
  console.log(uiEvent.button); // <- OK
};

Мы также можем явно указать информацию о типе для аргумента функции, чтобы переопределить любой контекстный тип:

window.onscroll = function (uiEvent: any) {
  console.log(uiEvent.button); // <- Now, no error is given
};

Однако, этот код выведет undefined, так как у uiEvent нет свойства, называемого button.

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

function createZoo(): Animal[] {
  return [new Rhino(), new Elephant(), new Snake()];
}

В этом примере наилучший общий тип имеет набор из четырёх кандидатов: Animal, Rhino, Elephant, и Snake. Из них Animal может быть выбран алгоритмом наилучшего общего типа.

© 2012-2023 Microsoft
Licensed under the Apache License, Version 2.0.
https://www.typescriptlang.org/docs/handbook/type-inference.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API