Choose Theme

Branded Types for IDs

· 2 min read · #TypeScript
--

Prevent accidentally mixing different ID types with branded types. TypeScript catches bugs at compile time.

branded-types.ts
// Create a branded type
type Brand<K, T> = K & { __brand: T };
// Define specific ID types
type UserId = Brand<string, 'UserId'>;
type PostId = Brand<string, 'PostId'>;
type CommentId = Brand<string, 'CommentId'>;
// Helper to create branded values
function userId(id: string): UserId {
return id as UserId;
}
function postId(id: string): PostId {
return id as PostId;
}
function commentId(id: string): CommentId {
return id as CommentId;
}
// Example usage
function getUser(id: UserId) {
return fetch(`/api/users/${id}`);
}
function getPost(id: PostId) {
return fetch(`/api/posts/${id}`);
}
const uid = userId('user-123');
const pid = postId('post-456');
getUser(uid); // ✅ Works
getUser(pid); // ❌ Type error! Can't use PostId as UserId
// Prevents bugs like:
// getUser(post.id) // Would be a runtime error

Bonus: UUID validation

import { z } from 'zod';
const userIdSchema = z.string().uuid().transform(id => id as UserId);
// Validates AND brands in one step
const validatedId = userIdSchema.parse('550e8400-e29b-41d4-a716-446655440000');

When to use:

  • APIs with multiple ID types
  • Preventing ID mix-ups in database queries
  • Type safety without runtime overhead

Related