Hack Frontend Community

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 Result type 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).

  • NumberType will equal number, since the numbers array 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.

  • ResolvedType will equal string, since Promise<string> extracts the string type.
  • NonPromiseType remains type number, since T is not a Promise.

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.