Using brands
- TypeScript course
- Advanced
- Lesson 19/57
- 4 min
Learn to use branded types in functions.
Branded parameters
Using branded types as function parameters prevents values of the wrong type from being passed. Instead of a plain string, only values with the correct brand are accepted; this catches confusion at compile time.
type UserId = Brand<string, "UserId">;
function getUser(id: UserId) {
return `user ${id}`;
}
const uid = "u1" as UserId;
getUser(uid); // valid
getUser("u1"); // error: not a plain stringCreating brands with validation
To create branded values safely, helper functions that validate are used. These functions check the input, brand it with as and return it if valid; throw an error if invalid. This way the brand is only created with valid values.
type Email = Brand<string, "Email">;
function makeEmail(s: string): Email {
if (!s.includes("@")) throw new Error("invalid email");
return s as Email;
}
const e = makeEmail("a@b.com"); // validPractice Create a brand with a validation helper
Define the Brand<T, B> helper type with intersection (using string brand). Create a UserId type. Write a makeUserId(s: string): UserId function that checks for empty string, returns with as UserId if valid, or throw new Error("empty") otherwise. Create a value via makeUserId("u1") and print it with console.log.
Starter code
// Brand<T, B> yardımcı türünü intersection ile tanımla
// UserId türünü Brand ile oluştur
// makeUserId fonksiyonunu validation ile yaz
// makeUserId("u1") ile değer oluştur ve yazdırSample solution
type Brand<T, B extends string> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
function makeUserId(s: string): UserId {
if (s.length === 0) throw new Error("empty");
return s as UserId;
}
const uid = makeUserId("u1");
console.log(uid);Expected output
u1
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Which of the following is a safety provided by a branded function parameter?
- String values are automatically converted to the brand
- Values with the wrong brand are rejected at compile time Correct answer
- The function runs faster
- Brand check performed at runtime
Explanation: Branded parameters provide compile-time type safety; values with the wrong brand (for example passing OrderId to a UserId parameter) cause a compile error.
2 Return a branded value after validation
type Brand<T, B extends string> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
function makeUserId(s: string): UserId {
if (s.length === 0) throw new Error("boş");
return s ____;
}
type Brand<T, B extends string> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
function makeUserId(s: string): UserId {
if (s.length === 0) throw new Error("boş");
return s as UserId;
}
Explanation: After validation passes, the value is branded with as UserId and returned; this ensures the brand is only created with valid input.
3 Brand usage parts
| Term | Meaning |
|---|---|
Brand'li parametre |
rejects wrong brand at compile time |
as UserId |
branding after validation |
makeUserId(s) |
validation and brand creation |
getUser("u1") |
compile error (plain string) |