diff --git a/apps/oxlint/src-js/utils/asserts.ts b/apps/oxlint/src-js/utils/asserts.ts index 917a0682e2af9..c75ead5dd8671 100644 --- a/apps/oxlint/src-js/utils/asserts.ts +++ b/apps/oxlint/src-js/utils/asserts.ts @@ -15,6 +15,9 @@ export function typeAssertIs(value: unknown): asserts value is T {} * In release builds, is a no-op. Only does runtime checks in debug builds. * Minification removes this function and all calls to it in release builds, so it has zero runtime cost. * + * Use this for testing conditions which would indicate a bug in the code. + * Do NOT use this for validating user input. + * * @param value - Value */ export function debugAssertIsNonNull(value: T | null | undefined): asserts value is T { @@ -25,3 +28,32 @@ export function debugAssertIsNonNull(value: T | null | undefined): asserts va throw new Error(`Expected non-null value, got ${value}`); } } + +/** + * Assert a condition. + * + * In release builds, is a no-op. Only does runtime checks in debug builds. + * Minification removes this function and all calls to it in release builds, so it has zero runtime cost. + * + * Use this for testing conditions which would indicate a bug in the code. + * Do NOT use this for validating user input. + * + * If creating the error message is expensive, or potentially creating the message itself can result in an error + * when the assertion passes, pass a function which returns the message. + * + * ```ts + * debugAssert(condition, () => `Condition failed: ${getErrorMessage()}`); + * ``` + * + * @param condition - Condition which is expected to be `true` + * @param message - Message to include in error if condition is `false`, + * or a function which returns the message to include in error if condition is `false` (optional). + */ +export function debugAssert(condition: boolean, message?: string | (() => string)): asserts condition { + if (!DEBUG) return; + + if (!condition) { + if (typeof message === 'function') message = message(); + throw new Error(message ?? 'Assertion failed'); + } +}