Senior LevelJavaScript & TypeScript
What is branded types / nominal typing in TypeScript and how does it prevent type confusion?
❓ Interview Prompt: Explain structural vs nominal typing, creating Brand symbols, and type-safe domain primitives (e.g. UserId vs PostId).
TypeScript uses a Structural Type System: two types are compatible if they have the same shape, regardless of their declared names.
The Problem:
A UserId (string) and a PostId (string) are structurally identical, allowing accidental parameter swapping without compiler errors!
The Branded Type Solution (Nominal Typing):
Attach a unique hidden tag (brand) to primitive types using type intersection. Forces TypeScript to treat structurally identical primitives as completely distinct domain types.
Code Implementation Example
typescript
// Branded Type Utility
declare const __brand: unique symbol;
type Brand<K, T> = K & { readonly [__brand]: T };
// Distinct domain types based on string
type UserId = Brand<string, 'UserId'>;
type PostId = Brand<string, 'PostId'>;
// Type Constructor Helpers
function makeUserId(id: string): UserId { return id as UserId; }
function makePostId(id: string): PostId { return id as PostId; }
function fetchPost(userId: UserId, postId: PostId) { /* ... */ }
const user = makeUserId('usr_123');
const post = makePostId('post_999');
fetchPost(user, post); // ✅ Allowed!
// fetchPost(post, user); // ❌ Compile Error! PostId is not assignable to UserId!💡Branded type intersections creating nominal type boundaries for IDs.
🎯 Interview Key Takeaway
Use branded types to turn structural primitive strings/numbers into distinct nominal domain types that prevent argument swapping.
#TypeScript#Branded Types#Nominal Typing#Senior
Back to all JavaScript & TypeScript Questions→