Unlocking the Power of TypeScript: Mastering the Infer Keyword

The Problem: Incomplete Typing

When working with third-party libraries, you’ve likely encountered situations where the library’s typing was incomplete or unclear. This can lead to frustrating errors and make it difficult to ensure type safety in your code.

Consider a third-party function, describePerson, that takes a person argument. If the library doesn’t provide a standalone type for the person argument, defining a variable beforehand won’t be inferred correctly by TypeScript. This can lead to errors and make it difficult to ensure type safety.

function describePerson(person: unknown) {
  //...
}

The Solution: Conditional Typing

One approach to resolve this issue is to use TypeScript conditional typing. This allows us to take a type and isolate any piece of it for later use. By combining conditional typing with the infer keyword, we can create efficient and flexible type checking and auto-completion.

type PersonType = T extends { name: string; age: number }? T : never;

const person: PersonType = {
  name: 'John',
  age: 30,
};

The Infer Keyword: Unwrapping Types

The infer keyword is used within conditional types to declare a type variable within our constraint to capture types dynamically within the extends clause of a conditional type. This allows us to extract and manipulate types from complex type operations, such as unions, arrays, and tuples.

type UnwrapType = T extends { type: infer U }? U : never;

type StringType = UnwrapType<{ type: string }>; // StringType is string
type NumberType = UnwrapType<{ type: number }>; // NumberType is number

Use Cases for the Infer Keyword

The infer keyword has several use cases, including:

  • Basic Usage: Capturing the actual type within a conditional type
  • Extracting Types from Unions: Extracting numeric types from a union type
  • Extracting Types from Arrays: Extracting the element type of an array
  • Extracting Types from Tuples: Converting a tuple type into a union type
  • Using Infer in Generic Functions: Defining types for function parameters and return types based on the inferred types from the function arguments or return values

Advanced Scenarios

The infer keyword can also be used in more complex scenarios, such as:

  • Flattening Nested Arrays: Recursively checking if a type is an array and extracting the element type
  • React Prop Types: Accessing prop types using the React utility type, ComponentProps
  • Functional Interfaces: Defining functional interfaces that can adapt to different input and output types
type FlattenArray = T extends Array? FlattenArray : T;

type NestedArrayType = FlattenArray<number[][][]>; // NestedArrayType is number</number[][][]>

Leave a Reply