Sikau

TypeScript · Day 13 · about 35 min

Project: Order tracker

Unions and narrowing in a real model.

States with their own data

A food delivery order is placed, then out for delivery (with a rider), then delivered (with a time) — or cancelled (with a reason). Model it with a discriminated union so impossible combinations can't exist.

Model the states first

Real delivery and booking apps model their orders exactly like this, often with many more states.

Before any code, list every state an order can be in and the data that exists only in that state. A placed order has just an id. A delivering order also has a rider. A delivered order has a delivery time. A cancelled order has a reason. Writing these as separate union members means an order can never be "delivered without a time" or "cancelled with a rider" — those combinations simply can't be built.

type Order =
  | { status: "placed"; id: number }
  | { status: "delivering"; id: number; rider: string }
  | { status: "delivered"; id: number; at: string }
  | { status: "cancelled"; id: number; reason: string };

This idea — "make illegal states unrepresentable" — is one of the most valuable habits typed programming teaches. Bugs that would need tests and careful checks in plain JavaScript are ruled out by the shape of the data itself.

The rest of this lesson

  • Moving between statesexplain
  • An impossible orderpredict
  • An order's lifeorder
  • State → its datamatch
  • Build the trackerchallenge
  • Badge quizquiz
  • Unit 2 complete!recap

Continue this lesson free — run real code in your browser

Continue with Google

See all 24 lessons of TypeScript