TypeScript Branded Types: Compile-Time Domain Modeling

Most TypeScript codebases treat domain identifiers as raw primitives. A userId is a string. An orderId is a string. A transaction amount is a number. TypeScript's structural type system sees them as identical shapes, so passing an orderId where a userId is expected compiles cleanly — until your database returns "user not found" at 2 AM and you spend an hour tracing a swapped argument.

This is primitive obsession, and branded types eliminate the entire problem class at compile time with zero runtime cost.