CodeBlanks Logo Icon CodeBlanks

Using brands

Learn to use branded types in functions.

Branded parameters

Using branded types as function parameters prevents values of the wrong type from being passed. Instead of a plain string, only values with the correct brand are accepted; this catches confusion at compile time.

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

function getUser(id: UserId) {
  return `user ${id}`;
}

const uid = "u1" as UserId;
getUser(uid);     // valid
getUser("u1");    // error: not a plain string

Creating brands with validation

To create branded values safely, helper functions that validate are used. These functions check the input, brand it with as and return it if valid; throw an error if invalid. This way the brand is only created with valid values.

type Email = Brand<string, "Email">;

function makeEmail(s: string): Email {
  if (!s.includes("@")) throw new Error("invalid email");
  return s as Email;
}

const e = makeEmail("a@b.com");  // valid

Practice Create a brand with a validation helper

Define the Brand<T, B> helper type with intersection (using string brand). Create a UserId type. Write a makeUserId(s: string): UserId function that checks for empty string, returns with as UserId if valid, or throw new Error("empty") otherwise. Create a value via makeUserId("u1") and print it with console.log.

Starter code

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

// UserId türünü Brand ile oluştur

// makeUserId fonksiyonunu validation ile yaz

// makeUserId("u1") ile değer oluştur ve yazdır

Sample solution

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

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

function makeUserId(s: string): UserId {
  if (s.length === 0) throw new Error("empty");
  return s as UserId;
}

const uid = makeUserId("u1");
console.log(uid);

Expected output

u1

Questions and answers

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

1 Which of the following is a safety provided by a branded function parameter?

  • String values are automatically converted to the brand
  • Values with the wrong brand are rejected at compile time Correct answer
  • The function runs faster
  • Brand check performed at runtime

Explanation: Branded parameters provide compile-time type safety; values with the wrong brand (for example passing OrderId to a UserId parameter) cause a compile error.

2 Return a branded value after validation

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

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

function makeUserId(s: string): UserId {
  if (s.length === 0) throw new Error("boş");
  return s ____;
}
Answer
type Brand<T, B extends string> = T & { readonly __brand: B };

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

function makeUserId(s: string): UserId {
  if (s.length === 0) throw new Error("boş");
  return s as UserId;
}

Explanation: After validation passes, the value is branded with as UserId and returned; this ensures the brand is only created with valid input.

3 Brand usage parts

Term Meaning
Brand'li parametre rejects wrong brand at compile time
as UserId branding after validation
makeUserId(s) validation and brand creation
getUser("u1") compile error (plain string)

All lessons in Advanced