← Back to Blog

Mastering TypeScript: Patterns I Use Every Day

TypeScript patterns engineering

After years of writing TypeScript, these are the patterns I reach for most often. They’ve saved me countless hours of debugging and made my codebase significantly more maintainable.

Discriminated Unions

Instead of optional fields that may or may not exist, use discriminated unions to model mutually exclusive states:

type Result<T> =
  | { status: "success"; data: T }
  | { status: "error"; message: string };

This forces you to handle every case and makes impossible states impossible.

Branded Types

Prevent mixing up different types of IDs or strings by adding a brand:

type UserId = string & { __brand: "UserId" };
type PostId = string & { __brand: "PostId" };

The satisfies Operator

Use satisfies to check that an expression matches a type without widening it:

const config = {
  api: "https://api.example.com",
  timeout: 5000,
} satisfies Record<string, string | number>;

TypeScript is a powerful tool — invest time in learning its advanced features and it will pay dividends.