What is a branded type?
- TypeScript course
- Advanced
- Lesson 17/57
- 4 min
Learn nominal-like typing with branded types.
What is a branded type?
TypeScript has a structural type system; two types with the same shape are mutually assignable. So type UserId = string and type OrderId = string are actually the same type and can be misused interchangeably. A branded type adds an invisible compile-time marker that makes these types structurally distinct, providing safety similar to nominal type systems.
type UserId = string;
type OrderId = string;
const uid: UserId = "u1";
const oid: OrderId = uid; // structural typing: valid but riskyNominal-like safety with brands
The brand pattern makes a base type structurally distinct by intersecting it with a marker. The marker field does not exist at runtime; it only distinguishes types at compile time. Thus UserId and OrderId cannot be assigned to each other even though they share the same base type.
type Brand<T, B> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
type OrderId = Brand<string, "OrderId">;
const uid = "u1" as UserId;
const oid: OrderId = uid; // error: types differPractice Separate two types with brands
Define the Brand<T, B> generic helper type using intersection. Use it to create UserId and OrderId types (both string-based). Create uid from "u1" as UserId, and oid from "o1" as OrderId via type assertion. Print both values with console.log.
Starter code
// Brand<T, B> generic yardımcı türünü intersection ile tanımla
// UserId ve OrderId türlerini Brand ile oluştur
// uid ve oid değerlerini uygun cast'lerle oluştur
// Her ikisini yazdırSample solution
type Brand<T, B> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
type OrderId = Brand<string, "OrderId">;
const uid = "u1" as UserId;
const oid = "o1" as OrderId;
console.log(uid);
console.log(oid);Expected output
u1 o1
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 For the definitions type UserId = string and type OrderId = string, which of the following is true?
- UserId accepts only string values starting with the 'u' prefix
- UserId and OrderId are structurally the same, so they are mutually assignable Correct answer
- UserId and OrderId cannot be assigned because they have different names
- The TypeScript compiler compares names
Explanation: TypeScript compares structural types by shape, not by name; since both aliases are string, they are structurally equivalent and mutually assignable.
2 Brand marker
type Brand<T, B> = T & { readonly ____: B };
type Brand<T, B> = T & { readonly __brand: B };
Explanation: The conventional brand marker is the __brand field; it does not exist at runtime but distinguishes types at compile time.
3 Branded type parts
| Term | Meaning |
|---|---|
Yapısal tip sistemi |
same shape = assignable |
Nominal tip sistemi |
different name = not assignable |
Brand pattern |
makes structural types behave like nominal |
__brand alanı |
compile-time marker |