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.