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(`Unexpected ${nullable}${msg ? `: ${messageToString(msg)}` : ""}`);
20 }
21 return nullable;
22}
23
24/** mark an incomplete feature. */
25export function TODO(msg?: Message): never {
26 throw new Error(`TODO${msg ? `: ${messageToString(msg)}` : ""}`);
27}
28
29/** assert that a `default` case in a switch is never reached. */
30export function unreachableCase(value: never): never {
31 throw new Error(`Unexpected value in switch: ${inspect(value as unknown)}`);
32}
33
34/** message called if function; then string printed as is or util inspectified */
35type Message = string | (() => string | unknown) | unknown;
36
37function messageToString(msg: Message) {
38 if (typeof msg === "function") msg = (msg as () => Message)();
39 return typeof msg === "string" ? msg : inspect(msg);
40}
41
42function inspect(object: unknown) {
43 try {
44 return node.builtin("util")?.inspect(object) ?? typeof object;
45 } catch {
46 return typeof object;
47 }
48}
49
50import * as node from "./node.ts";