Exhaustive check

2 snippets in TypeScript

TSTypeScript

never

TS · Basic Types
syntax
function varName(): never { ... }
example
function throwAppError(msg: string): never {
  throw new Error(msg);
}

// Used for exhaustive checks
type Shape = "circle" | "square";
function getArea(shape: Shape): number {
  switch (shape) {
    case "circle": return Math.PI * 10;
    case "square": return 100;
    default:
      const _exhaustive: never = shape;
      return _exhaustive;
  }
}
output
// never means this code path should be unreachable

Note never represents values that never occur. A function returning never must not return normally (throw or infinite loop). Assigning to never in a default branch ensures you handle every union member — adding a new Shape member causes a compile error.

Exhaustive Switch / If-Else

TS · Common Patterns
syntax
function assertNever(value: never): never {
  throw new Error(`Unexpected: ${value}`);
}
example
type PaymentMethod = "card" | "bank" | "crypto" | "paypal";

function processPayment(method: PaymentMethod): string {
  switch (method) {
    case "card":
      return "Processing card payment";
    case "bank":
      return "Processing bank transfer";
    case "crypto":
      return "Processing crypto payment";
    case "paypal":
      return "Processing PayPal";
    default:
      // If a new member is added to PaymentMethod,
      // this line causes a compile error
      const _exhaustive: never = method;
      throw new Error(`Unknown method: ${_exhaustive}`);
  }
}
output
// Adding a fifth payment method causes a compile error at the never assignment

Note The never trick ensures you handle every union member. When a new member is added, TypeScript sees it is not handled and cannot assign it to never. This is critical for state machines, reducers, and any logic that must cover all cases. Some teams extract this into a shared assertNever utility function.