Skip to content
GreenSnippets

Exhaustive switch with assertNever

Make the compiler fail when a union gains a new member that a switch does not handle.

TypeScript
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

function assertNever(value: never): never {
  throw new Error(`Unhandled variant: ${JSON.stringify(value)}`);
}

function area(shape: Shape): number {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.side ** 2;
    default:
      return assertNever(shape);
  }
}

How it works

Calling assertNever in the default branch means the argument must have type never. If someone adds a new variant to the union and forgets a case, the build fails at that exact line. At runtime it throws, which also catches bad data that bypassed the types.