--- name: typescript-patterns description: TypeScript type system patterns, generics, utility types, and strict mode best practices. Use when writing or reviewing TypeScript code. --- # TypeScript Patterns ## Core Rules - Strict mode always (`"strict": true`) - No `any` — use `unknown` for dynamic values - Explicit return types on all functions - `const` over `let`, never `var` ## Type Definitions ### Interfaces vs Types ```typescript // ✅ Interface for objects/classes (extensible) interface User { id: string email: string name: string } // ✅ Type for unions, primitives, computed type Status = 'active' | 'inactive' | 'pending' type UserOrAdmin = User | Admin type ReadonlyUser = Readonly ``` ### Generics ```typescript // ✅ Reusable generic types type ApiResponse = { data: T error: string | null status: number } type PaginatedResponse = { items: T[] total: number page: number limit: number } // ✅ Generic functions const findById = (items: T[], id: string): T | undefined => items.find(item => item.id === id) ``` ## Utility Types ```typescript // Pick specific fields type UserPreview = Pick // Omit sensitive fields type PublicUser = Omit // Make all optional (for partial updates) type UpdateUserDto = Partial // Make all required type RequiredUser = Required // Make all readonly type FrozenUser = Readonly // Extract from union type ActiveStatus = Extract // Record type type UserMap = Record ``` ## Discriminated Unions ```typescript // ✅ Type-safe error handling type Result = | { success: true; data: T } | { success: false; error: string } const processUser = (id: string): Result => { try { return { success: true, data: fetchUser(id) } } catch (e) { return { success: false, error: 'User not found' } } } // Usage — TypeScript knows the type const result = processUser('123') if (result.success) { console.log(result.data.name) // User } else { console.log(result.error) // string } ``` ## Type Guards ```typescript // ✅ Custom type guards const isUser = (value: unknown): value is User => typeof value === 'object' && value !== null && 'id' in value && 'email' in value // ✅ Assertion functions const assertDefined = (value: T | null | undefined): T => { if (value == null) throw new Error('Value is null or undefined') return value } ``` ## Async Patterns ```typescript // ✅ Always type async return values const fetchUser = async (id: string): Promise => { const res = await fetch(`/api/users/${id}`) if (!res.ok) throw new Error('Failed to fetch user') return res.json() as Promise } // ✅ Error handling with unknown try { await fetchUser(id) } catch (error) { if (error instanceof Error) { console.error(error.message) } } ``` ## Forbidden Patterns ```typescript // ❌ Never const data: any = fetchData() function process(x) { return x } // implicit any const obj = {} as User // unsafe assertion // @ts-ignore // suppressing errors ```