Ch. 2 · TypeScript

TypeScript Branded IDs and Domain Safety

TypeScript Branded IDs and Domain Safety. Learn the reasoning, a practical example, common mistakes and an interview exercise.

~2 min readadvancedupdated Oct 3, 2026

Brands distinguish otherwise identical primitive types in internal APIs. They reduce accidental swapping of IDs but need controlled construction at boundaries.

Before you start

You should be comfortable with JavaScript values, functions and objects. Use a TypeScript project with strict checking enabled when trying the examples. Separate what the compiler proves from what must still be checked when values arrive at runtime.

The practical goal is to reason through this situation: UserId and OrderId can both be strings while remaining incompatible in typed function signatures. Read the walkthrough first, then try the interview exercise before opening its answer. The important part is explaining the decision and its consequences, rather than remembering a definition alone.

Step-by-step walkthrough

Step 1: Separate domain identities

User IDs and order IDs may share string representation but represent different entities. Distinct types prevent accidental parameter swaps internally.

Step 2: Centralize construction

Validate the external string in a constructor before asserting the brand. Keep unchecked casting out of ordinary application code.

Step 3: Keep authorization independent

A valid branded ID does not prove the caller owns the record. Apply authorization when the operation is performed.

Worked scenario

UserId and OrderId can both be strings while remaining incompatible in typed function signatures.

declare const userBrand: unique symbol;
type UserId = string & { readonly [userBrand]: true };
function userId(value: string): UserId {
  if (!/^u_[0-9]+$/.test(value)) throw new Error('Invalid user ID');
  return value as UserId;
}
const id = userId('u_12');
TypeScript

The constructor establishes this example’s formatting rule; the brand records that distinction for typed consumers. The string has no magical runtime marker, and an unchecked cast could forge it.

Common mistake

An assertion can forge a brand, so branding is not authentication.

Verify the behavior

Test accepted and rejected formats, then add an OrderId type and verify a swapped call fails compilation. Test record ownership separately at the server boundary.

Interview exercise

Construct a branded ID safely.

Answer and reasoning

Validate the external string in a dedicated constructor, then apply the brand and keep unchecked casts localized.

Continue learning

Compare the scenario with the TypeScript interview questions and test your understanding with the TypeScript MCQs. For terminology and implementation details, consult the reference material.

More in TypeScript

read ✓TypeScript · hard

TypeScript Abstract Classes and Contracts

Share behavior with abstract classes, enforce required members, and decide when an interface or composition is the better contract.

~2 min readread →
read ✓TypeScript · mid

TypeScript Enums vs Union Types

Compare enums with unions of string literals: runtime cost, serialization, exhaustiveness and which one fits application code.

~3 min readread →
esc