CodeBlanks Logo Icon CodeBlanks

Summary - Exhaustive check

Write a safe state manager with exhaustive check.

Summary - Exhaustive check

Exhaustive check guarantees that switches processing union members are all exhaustive. With assertNever, the default branch takes a never parameter; if a case is missing, the compiler errors. This forces all processing sites to be updated when a new state is added in state managers.

type State = "idle" | "loading" | "ready" | "error";

function assertNever(x: never): never {
  throw new Error("Unexpected: " + x);
}

function transition(s: State): string {
  switch (s) {
    case "idle": return "Start";
    case "loading": return "Loading";
    case "ready": return "Ready";
    case "error": return "Error";
    default: return assertNever(s);
  }
}

Practice Write a state manager

Define an assertNever(x: never): never function (with throw new Error("Unexpected") inside). Define the State = "idle" | "loading" | "ready" | "error" union type. Write a transition(s: State): string function using switch (s): for idle return "Başlat", for loading return "Yükleniyor", for ready return "Hazır", for error return "Hata", for default write return assertNever(s);. Print results via console.log(transition("ready")) and console.log(transition("error")).

Starter code

index.ts
// assertNever fonksiyonunu tanımla (never parametre, never dönüş, throw içersin)

// State union türünü tanımla (idle, loading, ready, error)

// transition fonksiyonunu switch ile yaz, default'ta assertNever çağır

// "ready" ve "error" durumlarının sonuçlarını yazdır

Sample solution

index.ts
function assertNever(x: never): never {
  throw new Error("Unexpected");
}

type State = "idle" | "loading" | "ready" | "error";

function transition(s: State): string {
  switch (s) {
    case "idle":
      return "Başlat";
    case "loading":
      return "Yükleniyor";
    case "ready":
      return "Hazır";
    case "error":
      return "Hata";
    default:
      return assertNever(s);
  }
}

console.log(transition("ready"));
console.log(transition("error"));

Expected output

Hazır
Hata

Questions and answers

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

1 What happens when a new state is added to a state manager?

  • Existing cases are deleted
  • Missing cases in all switches cause compiler errors Correct answer
  • assertNever is called automatically
  • A runtime error is thrown

Explanation: When a new state is added, in switches with missing cases the variable in the default branch is not never; the assertNever call gives a compile error and reports the places to update.

2 Handle the error state

Question
function assertNever(x: never): never {
  throw new Error("Unexpected");
}

type State = "idle" | "loading" | "ready" | "error";

function transition(s: State): string {
  switch (s) {
    case "idle": return "Başlat";
    case "loading": return "Yükleniyor";
    case "ready": return "Hazır";
    case ____: return "Hata";
    default: return assertNever(s);
  }
}
Answer
function assertNever(x: never): never {
  throw new Error("Unexpected");
}

type State = "idle" | "loading" | "ready" | "error";

function transition(s: State): string {
  switch (s) {
    case "idle": return "Başlat";
    case "loading": return "Yükleniyor";
    case "ready": return "Hazır";
    case "error": return "Hata";
    default: return assertNever(s);
  }
}

Explanation: The case "error" narrows the State union to the error member; handling this state is required for the exhaustive check.

3 Exhaustive check summary matching

Term Meaning
assertNever(x: never) parameter must be never
default branch remaining after all cases
Yeni durum eklenince missing case errors at compile
Derleme zamanı güvenliği prevents runtime errors

All lessons in Advanced