Summary - Branded types
- TypeScript course
- Advanced
- Lesson 20/57
- 4 min
Write unmixable UserId and OrderId with branded types.
Summary - Branded types
Branded types add nominal safety to TypeScript's structural type system. The marker field added via intersection makes types based on the same base type structurally distinct. Using declare with a unique symbol reduces runtime cost to zero. Validation helpers ensure the brand is only created with valid values.
type Brand<T, B extends string> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
type OrderId = Brand<string, "OrderId">;
function makeUserId(s: string): UserId {
return s as UserId;
}
const uid = makeUserId("u1");
const oid: OrderId = uid; // error: UserId is not assignable to OrderIdPractice Write UserId and OrderId branded types
Define the Brand<T, B> helper type with intersection. Create UserId and OrderId types with separate brands. Write makeUserId(s: string): UserId and makeOrderId(s: string): OrderId helper functions (both return with as). Create a uid value via makeUserId("u1") and an oid value via makeOrderId("o1"). Print both with console.log. Then print console.log("done").
Starter code
// Brand<T, B> yardımcı türünü intersection ile tanımla
// UserId ve OrderId türlerini ayrı markalarla oluştur
// makeUserId ve makeOrderId yardımcı fonksiyonlarını yaz
// uid ve oid değerlerini oluştur ve yazdır, sonra "done" yazdırSample solution
type Brand<T, B extends string> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
type OrderId = Brand<string, "OrderId">;
function makeUserId(s: string): UserId {
return s as UserId;
}
function makeOrderId(s: string): OrderId {
return s as OrderId;
}
const uid = makeUserId("u1");
const oid = makeOrderId("o1");
console.log(uid);
console.log(oid);
console.log("done");Expected output
u1 o1 done
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What is the core benefit of the brand pattern?
- Provide automatic code completion
- Improve runtime performance
- Make types based on the same base type structurally distinct Correct answer
- Write shorter code
Explanation: The brand pattern provides nominal-like safety in a structural type system; it makes types based on the same base type (like UserId and OrderId) structurally distinct so they cannot be mixed up.
2 Separate UserId and OrderId with brands
type Brand<T, B extends string> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
// OrderId, UserId'den farklı olmalı:
type OrderId = Brand<string, ____>;
const uid = "u1" as UserId;
const oid: OrderId = uid; // hata: farklı markalar
type Brand<T, B extends string> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
// OrderId, UserId'den farklı olmalı:
type OrderId = Brand<string, "OrderId">;
const uid = "u1" as UserId;
const oid: OrderId = uid; // hata: farklı markalar
Explanation: For OrderId to differ from UserId, the brand string must be different; using "UserId" would make OrderId identical to UserId and they would be assignable.
3 Branded types summary matching
| Term | Meaning |
|---|---|
Yapısal tip sistemi |
same shape = assignable |
Brand pattern |
distinct types from the same base |
declare const __brand |
zero runtime code |
Validation yardımcısı |
brand only with valid values |