CodeBlanks Logo Icon CodeBlanks

What is a branded type?

Learn nominal-like typing with branded types.

What is a branded type?

TypeScript has a structural type system; two types with the same shape are mutually assignable. So type UserId = string and type OrderId = string are actually the same type and can be misused interchangeably. A branded type adds an invisible compile-time marker that makes these types structurally distinct, providing safety similar to nominal type systems.

type UserId = string;
type OrderId = string;

const uid: UserId = "u1";
const oid: OrderId = uid;  // structural typing: valid but risky

Nominal-like safety with brands

The brand pattern makes a base type structurally distinct by intersecting it with a marker. The marker field does not exist at runtime; it only distinguishes types at compile time. Thus UserId and OrderId cannot be assigned to each other even though they share the same base type.

type Brand<T, B> = T & { readonly __brand: B };

type UserId = Brand<string, "UserId">;
type OrderId = Brand<string, "OrderId">;

const uid = "u1" as UserId;
const oid: OrderId = uid;  // error: types differ

Practice Separate two types with brands

Define the Brand<T, B> generic helper type using intersection. Use it to create UserId and OrderId types (both string-based). Create uid from "u1" as UserId, and oid from "o1" as OrderId via type assertion. Print both values with console.log.

Starter code

index.ts
// Brand<T, B> generic yardımcı türünü intersection ile tanımla

// UserId ve OrderId türlerini Brand ile oluştur

// uid ve oid değerlerini uygun cast'lerle oluştur

// Her ikisini yazdır

Sample solution

index.ts
type Brand<T, B> = T & { readonly __brand: B };

type UserId = Brand<string, "UserId">;
type OrderId = Brand<string, "OrderId">;

const uid = "u1" as UserId;
const oid = "o1" as OrderId;

console.log(uid);
console.log(oid);

Expected output

u1
o1

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 For the definitions type UserId = string and type OrderId = string, which of the following is true?

  • UserId accepts only string values starting with the 'u' prefix
  • UserId and OrderId are structurally the same, so they are mutually assignable Correct answer
  • UserId and OrderId cannot be assigned because they have different names
  • The TypeScript compiler compares names

Explanation: TypeScript compares structural types by shape, not by name; since both aliases are string, they are structurally equivalent and mutually assignable.

2 Brand marker

Question
type Brand<T, B> = T & { readonly ____: B };
Answer
type Brand<T, B> = T & { readonly __brand: B };

Explanation: The conventional brand marker is the __brand field; it does not exist at runtime but distinguishes types at compile time.

3 Branded type parts

Term Meaning
Yapısal tip sistemi same shape = assignable
Nominal tip sistemi different name = not assignable
Brand pattern makes structural types behave like nominal
__brand alanı compile-time marker

All lessons in Advanced