CodeBlanks Logo Icon CodeBlanks

Switch exhaustive

Learn exhaustive checking in switches.

Switch exhaustive

In a switch statement, after all cases are written, ending the default branch with assertNever means that when a new member is added, the compiler finds all switches and reports the missing case. This guarantees the switch is exhaustive.

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

type Color = "red" | "green" | "blue";

function colorName(c: Color): string {
  switch (c) {
    case "red": return "Red";
    case "green": return "Green";
    case "blue": return "Blue";
    default: return assertNever(c);
  }
}

When a new member is added

While the existing switch is exhaustive, when a new member is added to the union, in switches that don't write all cases the c in the default branch is no longer never. The assertNever(c) call gives a compile error and reports the missing case.

type Color = "red" | "green" | "blue" | "yellow";  // yellow added

function colorName(c: Color): string {
  switch (c) {
    case "red": return "Red";
    case "green": return "Green";
    case "blue": return "Blue";
    // yellow case missing!
    default: return assertNever(c);  // error: c may now be "yellow"
  }
}

Practice Exhaustive with a Color switch

Define an assertNever(x: never): never function (with throw new Error("Unexpected") inside). Define the Color = "red" | "green" | "blue" union type. Write a colorName(c: Color): string function using switch (c): for red return "Kırmızı", for green return "Yeşil", for blue return "Mavi", for default write return assertNever(c);. Print the result via console.log(colorName("blue")).

Starter code

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

// Color union türünü tanımla (red, green, blue)

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

// "blue" renginin adını yazdır

Sample solution

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

type Color = "red" | "green" | "blue";

function colorName(c: Color): string {
  switch (c) {
    case "red":
      return "Kırmızı";
    case "green":
      return "Yeşil";
    case "blue":
      return "Mavi";
    default:
      return assertNever(c);
  }
}

console.log(colorName("blue"));

Expected output

Mavi

Questions and answers

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

1 What is done in the default branch to make the switch exhaustive?

  • break is used
  • return undefined is written
  • console.error is written
  • assertNever is called Correct answer

Explanation: If assertNever(c) is called in the default branch, when c is not never (a case is missing) a compile error occurs; this makes the switch exhaustive.

2 assertNever in default branch

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

type Color = "red" | "green" | "blue";

function colorName(c: Color): string {
  switch (c) {
    case "red": return "Kırmızı";
    case "green": return "Yeşil";
    case "blue": return "Mavi";
    default:
      return ____;
  }
}
Answer
function assertNever(x: never): never {
  throw new Error("Unexpected");
}

type Color = "red" | "green" | "blue";

function colorName(c: Color): string {
  switch (c) {
    case "red": return "Kırmızı";
    case "green": return "Yeşil";
    case "blue": return "Mavi";
    default:
      return assertNever(c);
  }
}

Explanation: Calling assertNever(c) in the default branch gives a compile error if c is not never; this guarantees the switch covers all members.

3 Switch exhaustive parts

Term Meaning
default branch remaining after all cases
assertNever(c) errors if c is not never
Yeni üye ekleme compiler catches missing case
switch ifadesi must be exhaustive

All lessons in Advanced