TypeScript Patterns I Use Every Single Day
These aren't the beginner patterns. These are the ones I reach for automatically now — the ones that make my code review comments shift from "this could break" to "this looks solid."
Discriminated Unions for State
type AsyncState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: string }The switch statement becomes exhaustive. TypeScript tells you when you've missed a case. No more forgotten error states.
Const Assertions for Config
const ROUTES = ['home', 'projects', 'contact'] as const
type Route = typeof ROUTES[number] // 'home' | 'projects' | 'contact'Your navigation logic can never reference a route that doesn't exist.
Template Literal Types
type EventName = `on${Capitalize<string>}`
// onLoad, onClick, onSubmit — but NOT load, click, submitSelf-documenting APIs that enforce conventions at the type level.
The Pattern That Saved Me Most
Wrapping external API responses in a Result type:
type Result<T, E = string> =
| { ok: true; value: T }
| { ok: false; error: E }Every function that can fail returns this. No more forgotten try/catch. No more null checks everywhere.
These patterns aren't clever. They're boring in the best way — they just make errors structurally impossible.