1/**
2 * assertions and type narrowing helpers. intended to be imported per symbol.
3 * functions are capitalized to make them stand out in a codebase.
4 *
5 * @module
6 */
7/* node:coverage disable */
8
9/** assert that `condition` is truthy. */
10export function ASSERT(condition: unknown, msg?: Message): asserts condition {
11 if (!condition) {
12 throw new Error(msg ? messageToString(msg) : "Assertion Error");
13 }
14}
15
16/** assert that `nullable` is non-null, returning a non-nullable T. */
17export function UNWRAP<T>(nullable: T | null | undefined, msg?: Message): T {
18 if (nullable == null) {
19 throw new Error(
20 `Unexpected ${nullable}${msg ? `: ${messageToString(msg)}` : ""}`,
21 );
22 }
23 return nullable;
24}
25
26/** assert that a `default` case in a switch is never reached. */
27export function unreachableCase(value: never): never {
28 throw new Error(`Unexpected value in switch: ${inspect(value as unknown)}`);
29}
30
31/** message called if function; then string printed as is or util inspectified */
32type Message = string | (() => string | unknown) | unknown;
33
34function messageToString(msg: Message) {
35 if (typeof msg === "function") msg = (msg as () => Message)();
36 return typeof msg === "string" ? msg : inspect(msg);
37}
38
39function inspect(object: unknown) {
40 try {
41 return node.builtin("util")?.inspect(object) ?? typeof object;
42 } catch {
43 return typeof object;
44 }
45}
46
47import * as node from "./node.ts";