Summary - Phantom types
- TypeScript course
- Advanced
- Lesson 24/57
- 4 min
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
// 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ırSample solution
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
type Order<S> = { amount: number };
type Pending = Order<"pending">;
type Paid = Order<"paid">;
type Shipped = Order<____>;
function ship(o: Paid): Shipped { return o; }
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 |