infer används inne i en conditional type för att fånga (extrahera) en typ från inom en annan typ in i en ny typvariabel som du sedan kan använda. Det är pattern-matching för typer.
<T> = T (infer U)[] ? U : ;
A = <[]>;
B = <[]>;
Läs det som: "om T matchar mönstret U[], binda U till vad som helst elementtypen är, och returnera det." infer U deklarerar en platshållare som kompilatorn fyller genom att matcha.
// the resolved type of a Promise
type Awaited2<T> = T extends Promise<infer R> ? R : T;
type R = Awaited2<Promise<User>>; // User
// a function's return type (this is how ReturnType is built)
type MyReturn<T> = T extends (...args: any[]) => infer R ? R : never;
type X = MyReturn<() => number>; // number
// a function's first parameter
type FirstArg<T> = T extends (a: infer A, ...rest: any[]) => any ? A : never;
type UnwrapBoth<T> =
T extends Promise<infer U> ? UnwrapBoth<U> : // recurse to unwrap nested promises
T extends (infer E)[] ? E : T;
Du kan använda flera infers i ett mönster och till och med rekursera.
infer är motorn bakom inbyggda typer som ReturnType, Parameters, Awaited och InstanceType, och bakom biblioteksmagin som härleder svarstyper från hämtare eller props från komponenter.
Det låter typad kod "öppna upp" en komplex typ och dra ut de inre bitarna — det mäktigaste verktyget för att skriva typer som anpassar sig till andra typer.