Skip to main content

Advanced TypeScript Utility Types: Mapped Types and Conditional Types

Mastering TypeScript's most powerful features: Mapped Types for object transformation and Conditional Types for complex type inference.

Published by Flutter Crafters, now part of LUMAQODE LTD1 min read
Code editor displaying complex TypeScript utility types
Code editor displaying complex TypeScript utility types

TypeScript's utility types are what elevate it from a simple type checker to a powerful tool for building robust, scalable codebases. Beyond the standard Partial and Readonly, the true power lies in Mapped Types and Conditional Types.

Mapped Types

Mapped types allow you to take an existing type and iterate over its keys to create a new type. This is the foundation for utilities like Partial<T>.

type Partial<T> = {
  [P in keyof T]?: T[P];
};

We can extend this to create a type where all properties are non-nullable (Required<T>), or a type where all properties are functions (FunctionProperties<T>).

Conditional Types (The "if-else" of Types)

Conditional types let you define a type based on a condition that checks if one type is assignable to another. The syntax is T extends U ? X : Y. The real magic comes with the infer keyword.

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

Here, infer R tells TypeScript: "If T is a function, figure out what its return type is and name it R, then use R as the resulting type." This is how you implement complex logic like extracting the type of an array element or the parameters of a function. Mastering these concepts is critical for writing high-quality library code.