/** * Exhaustiveness check for a `switch`/`if`-chain over a union type. Call * this in the `default` case (or final `else`) with the value being * switched on: if every member of the union has been handled by an * earlier branch, TypeScript narrows that value to `never` there, and the * call type-checks. If a new member is later added to the union and a * branch is forgotten, `value` is no longer `never` at that point — the * call becomes a **compile error**, catching the missing case before it * ships, instead of silently falling through at runtime. * * @example * type Shape = { kind: "circle"; radius: number } | { kind: "square"; side: number }; * * function area(shape: Shape): number { * switch (shape.kind) { * case "circle": * return Math.PI * shape.radius ** 2; * case "square": * return shape.side ** 2; * default: * // Compile error here if a new `Shape` variant is added without a * // matching case above — `shape` wouldn't be `never` anymore. * return assertIsNever(shape); * } * } * * @param value - The value that should be `never` at this point (compile-time check). * @param message - Optional custom error message; defaults to including the offending value. * @throws Always throws — this is also a real runtime safety net for a * value that reaches here despite the type system (e.g. unvalidated * external data cast to the union type). */ export function assertIsNever(value: never, message?: string): never { throw new Error(message ?? `Unexpected value: ${JSON.stringify(value)}`); }