infer
infer X — единственный способ «достать» внутренний тип из generic-обёртки. Используется в ReturnType, Awaited, Parameters. На интервью просят написать UnpackArray, UnpackPromise, извлекать первый и последний элементы кортежа.
Базовые инферы:
// Тип элемента массиваtype ArrayElem<T> = T extends (infer U)[] ? U : never;type N = ArrayElem<number[]>; // numbertype S = ArrayElem<readonly string[]>; // string
// Возврат функцииtype Ret<T> = T extends (...a: any[]) => infer R ? R : never;type R1 = Ret<() => Date>; // Date
// Распаковка Promisetype Unpromise<T> = T extends Promise<infer V> ? V : T;type P1 = Unpromise<Promise<number>>; // numberНесколько infer, голова и хвост кортежа:
type Head<T extends readonly any[]> = T extends [infer H, ...any[]] ? H : never;type Tail<T extends readonly any[]> = T extends [any, ...infer R] ? R : never;type Last<T extends readonly any[]> = T extends [...any[], infer L] ? L : never;
type H1 = Head<[1, 2, 3]>; // 1type T1 = Tail<[1, 2, 3]>; // [2, 3]type L1 = Last<[1, 2, 3]>; // 3
// Распаковка Awaited (рекурсивно)type AwaitedX<T> = T extends Promise<infer V> ? AwaitedX<V> : T;type A1 = AwaitedX<Promise<Promise<string>>>; // stringConstraint у infer (TS 4.7+) — фильтрует допустимые формы:
type FirstString<T extends readonly any[]> = T extends readonly [infer H extends string, ...any[]] ? H : never;
type W = FirstString<['a', 1, 2]>; // 'a'type Q = FirstString<[1, 'a']>; // neverИтог: infer работает только внутри ветки extends и достаёт любую позицию шаблона.