asterisks

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
8 min read
Ad Slot
TypeScript Tips: Advanced Patterns Every Developer Should Know

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