TypeScript
Brand definition
Learn to define a brand with intersection.
Brand definition
The brand helper type extends a base type with an intersection and a readonly property. This property is not accessible at runtime; it only distinguishes types at compile time. The B extends string constraint ensures a unique string is used for each brand.
type Brand<T, B extends string> = T & { readonly __brand: B };
type Email = Brand<string, "Email">;
const e: Email = "x@y.com" as Email;
declare with unique symbol
Using declare const to define a unique symbol and using it as the brand field makes accidental access harder. The symbol does not exist at runtime but distinguishes types at compile time. This provides stronger encapsulation.
declare const __brand: unique symbol;
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
Exercise Define a brand with a unique symbol
Use declare const __brand: unique symbol; to introduce the brand symbol. Define the Brand<T, B> helper type as an intersection with the [__brand] key. Use it to create an Email type (string-based). Create an Email value via type assertion from "x@y.com" and print it with console.log.
Show example solution
declare const __brand: unique symbol;
type Brand<T, B> = T & { readonly [__brand]: B };
type Email = Brand<string, "Email">;
const email = "x@y.com" as Email;
console.log(email);
Test yourself
-
What is the purpose of the B extends string constraint in the brand helper?
- To make the brand field visible at runtime
- To disable the intersection operation
- To restrict the base type to string
- To use a unique string marker for each brand
Show answer
To use a unique string marker for each brand — The B extends string constraint lets you use a different string for each brand; this makes types like UserId and OrderId structurally distinct from each other.
-
Brand symbol with declare
// Çalışma zamanı kodu olmadan benzersiz brand sembolü:
____
type Brand<T, B> = T & { readonly [__brand]: B };
Show answer
// Çalışma zamanı kodu olmadan benzersiz brand sembolü:
declare const __brand: unique symbol;
type Brand<T, B> = T & { readonly [__brand]: B };
-
Brand definition parts
- Brand yardımcı türü
- definition via intersection
- B extends string
- unique string per brand
- declare const __brand
- no runtime code
- unique symbol
- unique compile-time marker
Next lesson: Using brands