Assert Never Utility

1.4.0 · active · verified Sun Apr 19

The `assert-never` package provides a lightweight helper function designed for TypeScript's exhaustive checks on discriminated unions. Its primary purpose is to ensure that all possible cases of a union type are handled within a conditional block, leveraging the TypeScript compiler to catch unhandled cases at compile time. At runtime, if an unhandled case is encountered, `assertNever` will throw an `Error` by default, indicating a logical flaw. Alternatively, it can be configured to fail silently. The current stable version is 1.4.0. As a focused utility for a core TypeScript pattern, its release cadence is typically infrequent, with updates primarily for compatibility or minor feature enhancements rather than rapid iteration. Its key differentiator is its simplicity and direct application for a common TypeScript development pattern, making union type handling more robust.

Common errors

Warnings

Install

Imports

Quickstart

This example demonstrates how `assertNever` is used within a TypeScript switch statement to ensure exhaustive handling of a discriminated union `Shape`. If a new type is added to `Shape` but not handled in `getArea`, TypeScript will raise a compile-time error at the `assertNever` call. At runtime, if an unhandled type reaches this point, `assertNever` will throw an error.

import { assertNever } from "assert-never";

type Shape =
  | { type: 'circle'; radius: number }
  | { type: 'square'; side: number }
  | { type: 'triangle'; base: number; height: number };

function getArea(shape: Shape): number {
  switch (shape.type) {
    case 'circle':
      return Math.PI * shape.radius ** 2;
    case 'square':
      return shape.side ** 2;
    // If 'triangle' was added to Shape but not handled here, TypeScript would error.
    default:
      // TypeScript will error here if there are unhandled types in the union.
      // At runtime, if an unhandled shape reaches this point, it will throw an Error.
      return assertNever(shape);
  }
}

// Example usage
const myCircle: Shape = { type: 'circle', radius: 5 };
const mySquare: Shape = { type: 'square', side: 4 };
const myTriangle: Shape = { type: 'triangle', base: 3, height: 6 };

console.log("Area of circle:", getArea(myCircle));
console.log("Area of square:", getArea(mySquare));
console.log("Area of triangle:", getArea(myTriangle));

// To demonstrate the runtime error (uncomment the next lines to run):
// type NewShape = Shape | { type: 'pentagon'; side: number };
// const unhandledShape: NewShape = { type: 'pentagon', side: 5 };
// try {
//   // This line would cause a TypeScript error if getArea still expects 'Shape'
//   // and 'pentagon' is not handled. For runtime demo, we cast to bypass TS.
//   console.log("Area of unhandled shape:", getArea(unhandledShape as Shape));
// } catch (e: any) {
//   console.error("Caught expected runtime error:", e.message);
// }

view raw JSON →