Design state with types

INPUT · Slides

Design four states with types

01 / 03

A screen has four states

An app that fetches data has four possible states for its screen.

  • loading — waiting ("hang on…")
  • success — data arrived (show the list)
  • empty — data arrived but there is nothing (show "nothing here yet")
  • error — it failed ("try again")

TypeScript can write all four as a type.

02 / 03

A discriminated union for four branches

Use the discriminated union from chapter 3. Give every branch a shared marker called status, then line up four shapes with |.

Only success carries data. Only error carries message. What each state holds is different, and the type expresses that.

type ViewState =  | { status: "loading" }  | { status: "empty" }  | { status: "error"; message: string }  | { status: "success"; data: string[] };

03 / 03

switch and every case is narrowed

switch (state.status) branches into four, and TypeScript narrows the type in each case.

Inside "success", state.data exists. Inside "error", state.message exists. Touching the wrong property in the wrong state is impossible.

type ViewState =  | { status: "loading" }  | { status: "empty" }  | { status: "error"; message: string }  | { status: "success"; data: string[] };function render(state: ViewState): string {  switch (state.status) {    case "loading": return "Loading...";    case "empty":   return "No data";    case "error":   return `Error: ${state.message}`;    case "success": return state.data.join(", ");  }}console.log(render({ status: "success", data: ["Shopping", "Cleaning"] }));

Result

Shopping, Cleaning