CodeBlanks Logo Icon CodeBlanks

Brand definition

Learn to define a brand with intersection.

Brand definition

The brand helper type extends a base type with an intersection and a readonly property. This property is not accessible at runtime; it only distinguishes types at compile time. The B extends string constraint ensures a unique string is used for each brand.

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

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

const e: Email = "x@y.com" as Email;

declare with unique symbol

Using declare const to define a unique symbol and using it as the brand field makes accidental access harder. The symbol does not exist at runtime but distinguishes types at compile time. This provides stronger encapsulation.

declare const __brand: unique symbol;

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

Practice Define a brand with a unique symbol

Use declare const __brand: unique symbol; to introduce the brand symbol. Define the Brand<T, B> helper type as an intersection with the [__brand] key. Use it to create an Email type (string-based). Create an Email value via type assertion from "x@y.com" and print it with console.log.

Starter code

index.ts
// Çalışma zamanı kodu olmadan benzersiz brand sembolü tanıt

// Brand<T, B> yardımcı türünü sembol anahtarıyla tanımla

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

// Email değerini assertion ile oluştur ve yazdır

Sample solution

index.ts
declare const __brand: unique symbol;

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

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

const email = "x@y.com" as Email;
console.log(email);

Expected output

x@y.com

Questions and answers

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

1 What is the purpose of the B extends string constraint in the brand helper?

  • To make the brand field visible at runtime
  • To disable the intersection operation
  • To restrict the base type to string
  • To use a unique string marker for each brand Correct answer

Explanation: The B extends string constraint lets you use a different string for each brand; this makes types like UserId and OrderId structurally distinct from each other.

2 Brand symbol with declare

Question
// Çalışma zamanı kodu olmadan benzersiz brand sembolü:
____

type Brand<T, B> = T & { readonly [__brand]: B };
Answer
// Çalışma zamanı kodu olmadan benzersiz brand sembolü:
declare const __brand: unique symbol;

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

Explanation: declare const __brand: unique symbol declares a unique symbol type to the compiler without producing runtime code; since the brand is only used at compile time, this is ideal.

3 Brand definition parts

Term Meaning
Brand yardımcı türü definition via intersection
B extends string unique string per brand
declare const __brand no runtime code
unique symbol unique compile-time marker

All lessons in Advanced