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[][][]>