TypeScript

Branded Types (nominal typing)

admin by @admin ADMIN
Jun 15, 2026
May 31, 2026
Public
0 0 up · 0 down Sign in to vote
TypeScript is structurally typed, so `string` and `string` are interchangeable even when they semantically aren't (UserId vs PostId). The "brand" trick adds a phantom property that exists only at compile time, giving you nominal-ish typing.
TypeScript
Raw
type Brand<T, B> = T & { readonly __brand: B };

type UserId = Brand<string, 'UserId'>;
type PostId = Brand<string, 'PostId'>;

const asUserId = (s: string): UserId => s as UserId;
const asPostId = (s: string): PostId => s as PostId;

function deleteUser(id: UserId) { /* ... */ }

const u = asUserId('abc');
const p = asPostId('xyz');

deleteUser(u);   // ✓
deleteUser(p);   // ✗ Type 'PostId' is not assignable to 'UserId'
deleteUser('raw'); // ✗ raw strings rejected
Tags

Save your own code snippets

Create a free account and build your private vault. Share publicly whenever you want.