Mastering TypeScript Generics and Advanced Types
Introduction
TypeScript's type system is incredibly powerful, especially when you master generics and advanced type features. These tools allow you to write type-safe, reusable code that adapts to different data structures.
Basic Generics
typescript1// Generic function 2function identity<T>(value: T): T { 3 return value; 4} 5 6// Generic interface 7interface ApiResponse<T> { 8 data: T; 9 status: number; 10 message: string; 11} 12 13// Generic class 14class DataStore<T> { 15 private data: T[] = []; 16 17 add(item: T): void { 18 this.data.push(item); 19 } 20 21 get(index: number): T { 22 return this.data[index]; 23 } 24}
Conditional Types
Conditional types allow types to be selected based on conditions:
typescript1type IsString<T> = T extends string ? true : false; 2type A = IsString<'hello'>; // true 3type B = IsString<123>; // false 4 5// Extract properties of a specific type 6type StringKeys<T> = { 7 [K in keyof T]: T[K] extends string ? K : never; 8}[keyof T]; 9 10interface User { 11 id: number; 12 name: string; 13 email: string; 14 age: number; 15} 16 17type UserStringKeys = StringKeys<User>; // "name" | "email"
Mapped Types
Create new types by transforming existing ones:
typescript1type Optional<T> = { 2 [P in keyof T]?: T[P]; 3}; 4 5type Readonly<T> = { 6 readonly [P in keyof T]: T[P]; 7}; 8 9// Built-in mapped types in TypeScript 10// Partial<T>, Required<T>, Readonly<T>, Record<K, T>
Template Literal Types
typescript1type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; 2type ApiEndpoint = `/api/${string}`; 3type FullEndpoint = `${HttpMethod} ${ApiEndpoint}`; 4 5const endpoint: FullEndpoint = 'GET /api/users';
Real-World Example: API Client
typescript1interface ApiConfig { 2 baseURL: string; 3 timeout: number; 4} 5 6class ApiClient<T extends Record<string, any>> { 7 constructor(private config: ApiConfig) {} 8 9 async get<K extends keyof T>( 10 endpoint: K, 11 params?: Record<string, any> 12 ): Promise<T[K]> { 13 const response = await fetch( 14 `${this.config.baseURL}${endpoint as string}` 15 ); 16 return response.json(); 17 } 18} 19 20interface MyApiEndpoints { 21 '/users': User[]; 22 '/users/{id}': User; 23 '/posts': Post[]; 24} 25 26const api = new ApiClient<MyApiEndpoints>({ 27 baseURL: 'https://api.example.com', 28 timeout: 5000 29}); 30 31// Type-safe API calls 32const users = await api.get('/users'); // User[] 33const user = await api.get('/users/{id}'); // User