Тип вывода

TypeScript может вывести (проверить) типы переменных в соответствии с некоторыми простыми правилами. Вы можете быстро понять их на практике.

Определение переменных

Тип переменной, выведенной из определения:

let foo = 123; // foo is a `number`
let bar = "Hello"; // bar is a `string`

foo = bar; // Error: cannot assign `string` to a `number`

Это пример типов, проходящих справа налево.

Тип возврата функции

Тип возврата может быть выведен с помощью оператора return, как показано ниже. Функция вывода возвращает число:

function add(a: number, b: number) {
  return a + b;
}

Это пример типов, протекающих снизу вверх.

Присваивание

Типы функциональных параметров/возвращаемых значений также могут быть определены по присваиванию. Как показано ниже, тип foo - Adder, который позволяет параметрам a и b в foo иметь тип number.

type Adder = (a: number, b: number) => number;
let foo: Adder = (a, b) => a + b;

Этот факт может быть подтвержден следующим кодом: TypeScript выдаст предупреждение об ошибке, как вы и ожидали:

type Adder = (a: number, b: number) => number;
let foo: Adder = (a, b) => {
  a = 'hello'; // Error: cannot assign `string` to a `number`
  return a + b;
};

Это пример типов, проходящих слева направо.

Если вы создаете функцию, а параметр функции является функцией обратного вызова, к ней применяются те же правила назначения. argument к parameter - это просто еще одна форма назначения переменных.

type Adder = (a: number, b: number) => number;
function iTakeAnAdder(adder: Adder) {
  return adder(1, 2);
}

iTakeAnAdder((a, b) => {
  a = 'hello'; // Error: cannot assign `string` to a `number`
  return a + b;
});

Структурированные

Эти простые правила также применяются к структурированному существованию (объектные литералы), например, тип foo выводится как { a: number, b: number } в следующих случаях:

const foo = {
  a: 123,
  b: 456
};

foo.a = 'hello'; // Error:cannot assign `string` to a `number`

То же самое касается массивов:

const bar = [1, 2, 3];
bar[0] = 'hello'; // Error:cannot assign `string` to a `number`

Если параметры функции могут быть выведены, то и могут быть деконструированы. В следующем примере параметры функции могут быть деконструированы в члены a/b:

type Adder = (number: { a: number; b: number }) => number;
function iTakeAnAdder(adder: Adder) {
  return adder({ a: 1, b: 2 });
}

iTakeAnAdder(({ a, b }) => {
  // a, b Могут быть выведены
  a = 'hello'; // Error:cannot assign `string` to a `number`
  return a + b;
});

Тип защиты

В предыдущей главе Защита типов мы уже знали, как она может помочь нам изменить и сузить тип (особенно при объединении типов). Защита типов - это просто еще одна форма вывода переменных в блоке.

Предупреждения

Будьте осторожны с параметрами

Если тип не может быть выведен с помощью присваивания, тип не попадет в параметры функции. Например, в следующем примере компилятор не знает тип foo, поэтому он не может определить тип a или b.

const foo = (a, b) => {
  /* do something */
};

Однако, если foo описан по типу, параметры функции также могут быть выведены (a, b может быть выведен как number):

type TwoNumberFunction = (a: number, b: number) => void;
const foo: TwoNumberFunction = (a, b) => {
  /* do something */
};

Будьте осторожны с возвращаемыми значениями

Хотя TypeScript может обычно выводить возвращаемое значение функции, это может быть не то, что вам нужно. Например, следующая функция foo возвращает any:

function foo(a: number, b: number) {
  return a + addOne(b);
}

// Некоторые специальные функции, использующие библиотеки JavaScript
function addOne(a) {
  return a + 1;
}

Это связано с тем, что на тип возвращаемого значения влияет функция addOne, в которой отсутствует определение типа (значит оно равно any, поэтому addOne возвращает any, а foo также возвращает any).

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

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

noImplicitAny

Опция noImplicitAny используется, чтобы сообщить компилятору о возникновении ошибки, когда он не может вывести переменную (или он может быть выведен как неявный any тип), вы можете:

  • Сделать его any типом, явно добавив аннотацию типа :any;

  • Помочь TypeScript вывести типы с некоторыми более правильными аннотациями типов.

Last updated

Was this helpful?