// Frontend
TypeScript Advanced Patterns for Professional Developers
Master advanced TypeScript patterns including generics, utility types, and type-safe design patterns.
Md Nayeem HossainDec 10, 202413 min read// Frontend
Master advanced TypeScript patterns including generics, utility types, and type-safe design patterns.
Md Nayeem HossainDec 10, 202413 min read
Most developers know the basics of TypeScript: strings, numbers, and interfaces. But TypeScript's type system is incredibly powerful (Turing complete, actually!). Mastering advanced patterns allows you to write libraries and utilities that are robust and flexible.
Generics allow you to write code that works with a variety of types rather than a single one. Think of them as "variables for types."
1// Without generics, we lose type information2function getFirst(arr: any[]) {3 return arr[0]; // Return type is 'any'4}5 6// With generics7function getFirst<T>(arr: T[]): T | undefined {8 return arr[0];9}10 11const num = getFirst([1, 2, 3]); // Type is 'number'12const str = getFirst(["a", "b"]); // Type is 'string'TypeScript comes with built-in utilities that transform types.
Partial<T>: Makes all properties optional.Pick<T, K>: Selects a subset of properties.Omit<T, K>: Removes a subset of properties.1interface User {2 id: number;3 name: string;4 email: string;5 passwordHash: string;6}7 8// When updating a user, we might only provide some fields9type UpdateUserDto = Partial<User>;10 11// When displaying a user, we NEVER want to show the password12type UserProfile = Omit<User, 'passwordHash'>;This is my favorite pattern for state management (like in Redux or useReducer). It uses a common literal field (usually type or kind) to let TypeScript narrow down the type.
1type APIState =2 | { status: "loading" }3 | { status: "success"; data: User[] }4 | { status: "error"; error: string };5 6function handleState(state: APIState) {7 if (state.status === "loading") {8 // TypeScript knows 'data' and 'error' don't exist here9 return "Loading...";10 }11 12 if (state.status === "success") {13 // TypeScript knows 'data' exists here!14 return `Loaded ${state.data.length} users`;15 }16 17 if (state.status === "error") {18 return `Error: ${state.error}`;19 }20}This pattern makes "impossible states" impossible to represent in your code, eliminating entire classes of bugs.