infer Keyword in TypeScript — infer TypeScript
infer is a keyword in TypeScript used for type inference within conditional types. It allows TypeScript to automatically infer types depending on context, making code more flexible and avoiding type duplication.
infer is used in conjunction with conditional types to determine a type based on the structure of another type. This makes code more dynamic and reduces the need for explicit type specification in some situations.
How does infer work?
When you use infer, TypeScript can infer types without specifying them explicitly, based on how they're used within a conditional type. This allows creating more universal and flexible types.
infer Usage Examples
Inferring function return type
infer is often used to extract a function's return type from its type. This is useful when you need to get a type from an object or function without explicit type specification.
type ReturnTypeOfFunction<T> = T extends (...args: any[]) => infer R ? R : never;
function getString(): string {
return "Hello, world!";
}
type Result = ReturnTypeOfFunction<typeof getString>; // string
In this example, using infer R, TypeScript infers the return type of the getString function, which will be string.
ReturnTypeOfFunction<T>is a conditional type that checks if type T is a function. If yes, then infer R infers the function's return type.- The
Resulttype will be string, since getString function returns a string.
Using infer with arrays
infer can also be used to extract array element types.
type ElementType<T> = T extends (infer U)[] ? U : never;
const numbers: number[] = [1, 2, 3];
type NumberType = ElementType<typeof numbers>; // number
Here, the ElementType<T> type checks if type T is an array. If so, infer U extracts the array element type (in our case number).
NumberTypewill equalnumber, since thenumbersarray contains number type elements.
Conditional infer usage in more complex types
infer can be useful for extracting types in more complex types such as objects, classes and other data structures.
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type ResolvedType = UnwrapPromise<Promise<string>>; // string
type NonPromiseType = UnwrapPromise<number>; // number
In this example UnwrapPromise<T> is a conditional type that extracts the type referenced by Promise. If T is a Promise, then infer U extracts the type wrapped in Promise, in this case string.
ResolvedTypewill equalstring, sincePromise<string>extracts thestringtype.NonPromiseTyperemains typenumber, sinceTis not aPromise.
When to use infer?
- When you need to extract a type from a function or object without specifying it explicitly.
- For working with more complex types such as arrays, promises and other types where you need to extract element types.
- For creating universal types that can adapt to different situations, helping avoid code duplication and increasing flexibility.
Recommendation:
Use infer to extract types in conditional types to make code more flexible and avoid duplication. This is especially useful when working with functions, arrays and complex types.