Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Branded types let TypeScript distinguish values that share the same runtime representation, such as a UserId and an OrderId. A brand is a compile-time distinction, not runtime validation: check a value at a parser or constructor boundary, then treat it as branded only after it passes.

What are branded types in TypeScript?

A branded type is a type-system pattern for making semantically different values incompatible even when their underlying values have the same shape. For example, both user IDs and order IDs may be strings, but passing an order ID to a function that expects a user ID is likely a mistake.

TypeScript uses structural compatibility: it compares members rather than treating each type name as a separate nominal identity. Consequently, type UserId = string and type OrderId = string are both just aliases for string; either can be used where the other is expected. The TypeScript Handbook’s explanation of type compatibility describes this structural model.

How do branded types prevent ID mix-ups?

A common technique intersects the base type with an object type containing a brand-only property. Declare a separate unique symbol for each semantic type:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
declare const userIdBrand: unique symbol;
declare const orderIdBrand: unique symbol;

type UserId = string & { readonly [userIdBrand]: true };
type OrderId = string & { readonly [orderIdBrand]: true };

function loadUser(id: UserId) {
  // Load the user identified by id.
}

function loadOrder(id: OrderId) {
  // Load the order identified by id.
}

The properties are a type-level device; they do not need to exist on the string at runtime. Each unique symbol has an identity tied to its declaration, so the two branded types have distinct keys and are not interchangeable. The TypeScript Handbook’s Symbols documentation covers that identity rule.

With these definitions, a plain string is not automatically a UserId, and a OrderId is not a UserId. That forces code to make the conversion explicit at a deliberate boundary.

Rank #2
TypeScript Programming Language - Software Engineer & Coder T-Shirt
  • TypeScript implements a superset of syntax for strictly typed development, facilitating deep static analysis and enhanced development environment integration. The compiler translates source into standard script formats, ensuring parity across any runtime.
  • TypeScript is ideal for front-end developers, full-stack engineers, and software architects who build large-scale web applications. It serves those looking to improve code excellence, reduce bugs through static checking, and maintain complex projects more.
  • Lightweight, Classic fit, Double-needle sleeve and bottom hem

How do you create a branded type safely?

Define the brand, validate the input where it enters the domain, and keep the assertion inside that boundary. For example, if this application’s user IDs must begin with usr_:

function parseUserId(value: string): UserId {
  if (!value.startsWith("usr_")) {
    throw new Error("Invalid user ID");
  }

  return value as UserId;
}

The prefix check enforces this example’s rule at runtime. The as UserId assertion does not check the value; it tells the compiler to treat the checked string as branded. If the assertion is used without a real check, the brand provides no protection against invalid data.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

This boundary pattern is also useful for values other than IDs, such as a string that has passed a particular validation step. Choose the rule that matters to your application and put its check in the parser or constructor that grants the brand. A brand alone does not define what makes a value valid.

Which branding pattern should you use?

Pattern What it provides Trade-off
Plain alias, such as type UserId = string A descriptive name for a type Does not distinguish structurally identical values.
String-key brand with distinct literal tags A convenient branding property for a helper type Reusing the same base and branding identifier can make two intended brands equivalent.
unique symbol brand Declaration-specific property-key identity Requires symbol declarations and deliberate export or sharing when used across modules.
Runtime wrapper object or class Can represent identity or behavior at runtime as well as in the type system Changes the runtime representation; an intersection brand over a primitive does not.

For local distinctions such as user and order IDs, separate unique symbol declarations make the intended difference clear. A generic helper can also be convenient, provided each semantic brand receives a distinct identifier. The ts-brand documentation notes that brands with the same base type and branding type are considered the same type.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Where should brands enter and leave your code?

  • Apply them where the distinction matters. Brand domain values at boundaries where confusing them could cause incorrect behavior, rather than adding ceremony to every string.
  • Centralize construction. Prefer a parser or constructor that performs the relevant check before asserting the brand.
  • Keep assertions narrow and visible. A cast can bypass the intended validation, so avoid scattering brand assertions through application code.
  • Use separate identifiers. Give each semantic type its own unique symbol or distinct branding tag; otherwise the compiler may see the types as equivalent.

Branded types improve compile-time checking within TypeScript. They do not change a value’s runtime representation, validate data received from an API, or prevent code from deliberately using an assertion to bypass the distinction.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.