Весной стартует сезон найма, успей отхватить свой оффер!

Ключевое слово infer в TypeScript

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

infer используется в связке с условными типами для определения типа в зависимости от структуры другого типа. Это позволяет сделать код более динамичным и сокращает необходимость в явном указании типа в некоторых ситуациях.

Как работает infer?

Когда вы используете infer, TypeScript может выводить типы, не задавая их явно, основываясь на том, как они используются внутри условного типа. Это позволяет создавать более универсальные и гибкие типы.

Пример использования infer

Вывод типа возвращаемого значения функции

infer часто используется для извлечения типа возвращаемого значения функции из её типа. Это полезно, когда вам нужно получить тип из объекта или функции без явного указания типа.

type ReturnTypeOfFunction<T> = T extends (...args: any[]) => infer R ? R : never;

function getString(): string {
  return "Hello, world!";
}

type Result = ReturnTypeOfFunction<typeof getString>;  // string

В этом примере, с помощью infer R, TypeScript выводит тип возвращаемого значения функции getString, который будет string.

  • ReturnTypeOfFunction<T> — это условный тип, который проверяет, является ли тип T функцией. Если да, то infer R выводит тип возвращаемого значения функции.
  • Тип Result будет равен string, так как функция getString возвращает строку.

Использование infer для работы с массивами

infer также может использоваться для извлечения типа элементов массива.

type ElementType<T> = T extends (infer U)[] ? U : never;

const numbers: number[] = [1, 2, 3];
type NumberType = ElementType<typeof numbers>;  // number

Здесь, тип ElementType<T> проверяет, является ли тип T массивом. Если это так, infer U извлекает тип элементов массива (в нашем случае number).

  • NumberType будет равно number, так как массив numbers содержит элементы типа number.

Условное использование infer в более сложных типах

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

type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;

type ResolvedType = UnwrapPromise<Promise<string>>;  // string
type NonPromiseType = UnwrapPromise<number>;  // number

В этом примере UnwrapPromise<T> — это условный тип, который извлекает тип, на который ссылается Promise. Если T является Promise, то infer U извлекает тип, который был обернут в Promise, в данном случае это string.

  • ResolvedType будет равно string, так как Promise<string> извлекает тип string.
  • NonPromiseType остаётся типом number, так как T не является Promise.

Когда использовать infer?

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

Рекомендация:

Используйте infer для извлечения типов в условных типах, чтобы сделать код более гибким и избежать дублирования. Это особенно полезно при работе с функциями, массивами и сложными типами.