CodeBlanks Logo Icon CodeBlanks

Summary - Phantom types

Write a state-safe order flow with phantom types.

Summary - Phantom types

Phantom types provide type safety via unused generic parameters. With state encoding we encode state machines into the type; invalid transitions become compile errors. In API design they prevent functions from being called in the wrong order. There is no runtime cost; all safety is at compile time.

type Order<S> = { amount: number };

type Pending = Order<"pending">;
type Paid = Order<"paid">;
type Shipped = Order<"shipped">;

function pay(o: Pending): Paid { return o; }
function ship(o: Paid): Shipped { return o; }
function deliver(o: Shipped): string { return `delivered ${o.amount}`; }

const p: Pending = { amount: 10 };
const result = deliver(ship(pay(p)));

Practice Order flow with phantoms

Define the Order<S> generic type (body amount: number). Create Pending, Paid, Shipped types with phantom arguments. Write pay(o: Pending): Paid, ship(o: Paid): Shipped, and deliver(o: Shipped): string functions (deliver returns `delivered ${o.amount}`). Start from a Pending value, apply pay, ship, deliver in order, and print the result via console.log.

Starter code

index.ts
// Order<S> generic türünü tanımla (S gövdede kullanılmasın)

// Pending, Paid, Shipped türlerini phantom argümanlarla oluştur

// pay, ship, deliver fonksiyonlarını yaz

// Pending değerinden başla, pay/ship/deliver uygula, sonucu yazdır

Sample solution

index.ts
type Order<S> = { amount: number };

type Pending = Order<"pending">;
type Paid = Order<"paid">;
type Shipped = Order<"shipped">;

function pay(o: Pending): Paid {
  return o;
}

function ship(o: Paid): Shipped {
  return o;
}

function deliver(o: Shipped): string {
  return `delivered ${o.amount}`;
}

const p: Pending = { amount: 10 };
const result = deliver(ship(pay(p)));

console.log(result);

Expected output

delivered 10

Questions and answers

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

1 What is the runtime cost of phantom types?

  • Adds runtime type information
  • One byte per phantom parameter
  • Zero Correct answer
  • A computation per state transition

Explanation: The phantom parameter exists only at the type level and is erased after compilation. There is no extra value or check at runtime.

2 Three-state order flow

Question
type Order<S> = { amount: number };
type Pending = Order<"pending">;
type Paid = Order<"paid">;
type Shipped = Order<____>;

function ship(o: Paid): Shipped { return o; }
Answer
type Order<S> = { amount: number };
type Pending = Order<"pending">;
type Paid = Order<"paid">;
type Shipped = Order<"shipped">;

function ship(o: Paid): Shipped { return o; }

Explanation: The Shipped state is represented by its own phantom argument; the ship function takes Paid and returns Shipped, and the transition is enforced at the type level.

3 Phantom types summary matching

Term Meaning
Phantom parametre generic parameter not used in body
State encoding encode states into type
Geçiş fonksiyonu rejects wrong state at compile time
Çalışma zamanı maliyeti zero

All lessons in Advanced