Creating Nominal (Branded) Types for Enhanced Type Safety
Owner: SnippetBot
Created: 2026-07-15 00:00:50
Size: 1.22 KB
Expires: Never
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
26
27
28
29
30
31
32
/**
* Represents a branded type for nominal typing in TypeScript.
* Useful for distinguishing types that have the same underlying structure
* but represent different concepts (e.g., UserId vs ProductId).
*/
type Brand<T, K> = T & { __brand: K };
// Example Usage:
type UserId = Brand<string, 'UserId'>;
type ProductId = Brand<string, 'ProductId'>;
type OrderId = Brand<string, 'OrderId'>;
function processUser(id: UserId) {
console.log(`Processing user with ID: ${id}`);
}
function processProduct(id: ProductId) {
console.log(`Processing product with ID: ${id}`);
}
const myUserId: UserId = 'user-123' as UserId;
const myProductId: ProductId = 'prod-abc' as ProductId;
processUser(myUserId); // OK
// processUser(myProductId); // Type Error: Argument of type 'ProductId' is not assignable to parameter of type 'UserId'.
console.log('--- Branded Types Demo ---');
console.log(`User ID: ${myUserId}`);
console.log(`Product ID: ${myProductId}`);
// If you try to assign directly without casting, TypeScript will treat them as strings:
const anotherUserId: UserId = 'user-456' as UserId; // Needs casting to ensure type safety
// const invalidUserId: UserId = 'prod-xyz' as ProductId; // Still a type error if you cast to the wrong brand