Skip to content
← Back to rules

typescript/switch-exhaustiveness-check Pedantic

💭 This rule requires type information.
💡 A suggestion is available for this rule for some violations.

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

Regular expression pattern for a comment that acts as an omitted default case. The comment must appear after the final case and the switch must not have a default case. For union types, it suppresses the exhaustiveness check only when considerDefaultExhaustiveForUnions is enabled. Example: "^skip default$" to allow a switch ending in // skip default.

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
{
  "options": {
    "typeAware": true
  },
  "rules": {
    "typescript/switch-exhaustiveness-check": "error"
  }
}
ts
import { defineConfig } from "oxlint";

export default defineConfig({
  options: { typeAware: true },
  rules: {
    "typescript/switch-exhaustiveness-check": "error",
  },
});
bash
oxlint --type-aware --deny typescript/switch-exhaustiveness-check

Version ​

This rule was added in v1.12.0.

References ​