infer bruges inde i en conditional type til at fange (udtrække) en type fra inden i en anden type til en ny typevariabel, som du derefter kan bruge. Det er pattern-matching for typer.
<T> = T (infer U)[] ? U : ;
A = <[]>;
B = <[]>;
Læs det som: "hvis T matcher mønsteret U[], bind U til hvad end elementtypen er, og returner det." infer U erklærer en placeholder, som kompileren udfylder ved matching.
// 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 bruge flere infers i ét mønster og endda rekursion.
infer er motoren bag indbyggede typer som ReturnType, Parameters, Awaited og InstanceType, og bag biblioteksmagien, der udleder svarstyper fra fetchers eller props fra komponenter.
Det giver typekode mulighed for at "åbne" en kompleks type og trække de indre dele ud — det mest kraftfulde værktøj til at skrive typer, der tilpasser sig andre typer.