Skip to content
← Back to rules

typescript/switch-exhaustiveness-check Pedantic

💭 This rule requires type information.
🚧 An auto-fix is planned for this rule, but not implemented at this time.

What it does

This rule requires switch statements to be exhaustive when switching on union types.

Why is this bad?

When switching on a union type, it's important to handle all possible cases to avoid runtime errors. TypeScript can help ensure exhaustiveness, but only if the switch statement is properly structured with a default case that TypeScript can analyze.

Examples

Examples of incorrect code for this rule:

ts
type Status = "pending" | "approved" | "rejected";

function handleStatus(status: Status) {
  switch (status) {
    case "pending":
      return "Waiting for approval";
    case "approved":
      return "Request approved";
    // Missing 'rejected' case
  }
}

enum Color {
  Red,
  Green,
  Blue,
}

function getColorName(color: Color) {
  switch (color) {
    case Color.Red:
      return "red";
    case Color.Green:
      return "green";
    // Missing Color.Blue case
  }
}

Examples of correct code for this rule:

ts
type Status = "pending" | "approved" | "rejected";

function handleStatus(status: Status) {
  switch (status) {
    case "pending":
      return "Waiting for approval";
    case "approved":
      return "Request approved";
    case "rejected":
      return "Request rejected";
  }
}

// Or with default case for exhaustiveness checking
function handleStatusWithDefault(status: Status) {
  switch (status) {
    case "pending":
      return "Waiting for approval";
    case "approved":
      return "Request approved";
    case "rejected":
      return "Request rejected";
    default:
      const _exhaustiveCheck: never = status;
      return _exhaustiveCheck;
  }
}

enum Color {
  Red,
  Green,
  Blue,
}

function getColorName(color: Color) {
  switch (color) {
    case Color.Red:
      return "red";
    case Color.Green:
      return "green";
    case Color.Blue:
      return "blue";
    default:
      const _exhaustiveCheck: never = color;
      return _exhaustiveCheck;
  }
}

Configuration

This rule accepts a configuration object with the following properties:

allowDefaultCaseForExhaustiveSwitch

type: boolean

default: true

Whether to allow default cases on switches that are not exhaustive. When false, requires exhaustive switch statements without default cases.

considerDefaultExhaustiveForUnions

type: boolean

default: false

Whether to consider default cases exhaustive for union types. When true, a switch statement with a default case is considered exhaustive even if not all union members are handled explicitly.

defaultCaseCommentPattern

type: string | null

Regular expression pattern that when matched in a default case comment, will suppress the exhaustiveness check. Example: "@skip-exhaustive-check" to allow default: // @skip-exhaustive-check

requireDefaultForNonUnion

type: boolean

default: false

Whether to require default cases on switches over union types that are not exhaustive. When true, switches with non-exhaustive union types must have a default case.

How to use

To enable this rule using the config file or in the CLI, you can use:

json
{
  "rules": {
    "typescript/switch-exhaustiveness-check": "error"
  }
}
bash
oxlint --type-aware --deny typescript/switch-exhaustiveness-check

References