August 4, 2024
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.
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>`.
```typescript
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.
```typescript
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.