Branded type
A branded type is a TypeScript pattern that distinguishes structurally-identical types by adding a phantom 'brand' property — UserId and ProductId can both be string at runtime but cannot be assigned to each other at compile time. The pattern prevents accidentally passing a UserId where a ProductId is expected.
TypeScript is structurally typed by default, so two string aliases are interchangeable. Branding fakes nominal typing: type UserId = string & { readonly __brand: 'UserId' }. The runtime representation is just a string; the compile-time check enforces the distinction. The trade-off: every conversion needs a cast (or a helper like brand<UserId>(s)), which adds friction. The discipline pays for itself in domains with many identifier types — order IDs, customer IDs, SKU IDs, payment intents — where mixing them up is a recurring bug source. Stride uses branded types for entity IDs at the data-access layer.
Related terms
- Discriminated union
A discriminated union is a union type whose variants share a literal-typed property (the discriminant) that uniquely identifies each variant — typically named 'type', 'kind', or 'tag'.
- Type narrowing
Type narrowing is TypeScript's ability to refine a value's type within a conditional branch based on runtime checks — typeof, instanceof, in operator, equality checks, custom type predicates.
- TypeScript strict mode
TypeScript's strict mode enables a bundle of compiler flags that produce stricter type checking — noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, alwaysStrict, strictPropertyInitialization, noImplicitThis.