typescript / expert
Snippet
Zero-Cost Nominal Type Branding via Unique Symbol Enclosure
TypeScript uses a structural type system, meaning two types with identical structures are interchangeable. Nominal branding simulates nominal typing by attaching a hidden type tag bound to a unique symbol. This prevents domain errors such as accidentally passing an OrderId string into a function requiring a UserId string, incurring zero JavaScript runtime overhead.
snippet.ts
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
declare const brandSymbol: unique symbol;export type Brand<T, B extends string> = T & {readonly [brandSymbol]: B;};type UserId = Brand<string, "UserId">;type OrderId = Brand<string, "OrderId">;function createUserId(raw: string): UserId {if (!raw.startsWith("usr_")) throw new Error("Invalid User ID format");return raw as UserId;}function createOrderId(raw: string): OrderId {if (!raw.startsWith("ord_")) throw new Error("Invalid Order ID format");return raw as OrderId;}function fetchUserOrders(userId: UserId): void {console.log(`Fetching orders for user ${userId}`);}const validUser = createUserId("usr_9981");fetchUserOrders(validUser);
Breakdown
1
declare const brandSymbol: unique symbol;
Declares a unique symbol accessible only at compile time to key the phantom branding property.
2
export type Brand<T, B extends string> = T & { readonly [brandSymbol]: B; };
Intersects base type T with an unconstructable phantom property tag to enforce strict type identity.
3
function createUserId(raw: string): UserId
Acts as a constructor validator function that casts a raw primitive string into a branded UserId.
4
function fetchUserOrders(userId: UserId): void
Restricts parameter input exclusively to valid UserId brands, rejecting plain strings or OrderIds.