TypeScript Tips: Advanced Patterns Every Developer Should Know
From discriminated unions to template literal types, explore the TypeScript patterns that will make your code safer and more expressive.
D
Deepak
Ad Slot
TypeScript has become the lingua franca of modern frontend development. But beyond basic types and interfaces, there’s a world of advanced patterns that can transform your codebase.
Discriminated Unions
Discriminated unions are TypeScript’s most powerful pattern for modeling state:
type LoadingState =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: User[] }
| { status: 'error'; error: Error };
function render(state: LoadingState) {
switch (state.status) {
case 'idle': return <Empty />;
case 'loading': return <Spinner />;
case 'success': return <List data={state.data} />;
case 'error': return <Error message={state.error.message} />;
}
}
Template Literal Types
Build powerful string-based types:
type EventName = 'click' | 'focus' | 'blur';
type Handler = `on${Capitalize<EventName>}`;
// "onClick" | "onFocus" | "onBlur"
type Routes = '/home' | '/blog' | '/about';
type ApiRoute = `/api${Routes}`;
// "/api/home" | "/api/blog" | "/api/about"
Utility Types Deep Dive
TypeScript ships with powerful built-in utilities:
interface User {
id: string;
name: string;
email: string;
role: 'admin' | 'user';
}
// Make all fields optional
type PartialUser = Partial<User>;
// Make all fields required
type RequiredUser = Required<User>;
// Pick specific fields
type PublicUser = Pick<User, 'id' | 'name'>;
// Omit sensitive fields
type SafeUser = Omit<User, 'email'>;
// Extract from union
type AdminRole = Extract<User['role'], 'admin'>;
Conditional Types
type IsArray<T> = T extends any[] ? true : false;
type Flatten<T> = T extends Array<infer Item> ? Item : T;
type A = Flatten<string[]>; // string
type B = Flatten<number>; // number
The satisfies Operator
New in TypeScript 4.9, satisfies validates a type without widening it:
const palette = {
red: [255, 0, 0],
green: '#00ff00',
} satisfies Record<string, string | number[]>;
// TypeScript knows the exact shapes
palette.red.map(x => x * 2); // ✅
palette.green.toUpperCase(); // ✅
These patterns will make your TypeScript code more expressive, safe, and maintainable.
Ad Slot