/** * Assertion function with fixable stack for better error messages */ export function assert(cond: boolean, message: string, offsetStack?: number) { if (!cond) { const error = new Error(message); const stack = error.stack; if (stack) { // https://kentcdodds.com/blog/improve-test-error-messages-of-your-abstractions const lines = stack.trim().split("\n"); const errorMessage: string[] = []; const stackLines: string[] = []; for (const line of lines) { // Strack trace lines starts with " at " if (/^\s*at /.test(line)) { stackLines.push(line); } else { errorMessage.push(line); } } error.stack = errorMessage .concat(stackLines.slice(offsetStack ?? 1)) .join("\n"); } throw error; } } /** * Given object is null or undefined */ export function isNil(ob: any): ob is null | undefined { return ob === null || ob === undefined; } /** * Given object is NOT null or undefined */ export function notNil(ob: T): ob is Exclude { return ob !== null && ob !== undefined; } /** * Asserts that given object is not false, null or undefined */ export function assertNotNil( ob: T, msg?: string, ): asserts ob is Exclude { if (!msg) { msg = `Unexpected ${_stringify(ob)}`; } assert(!isNil(ob), `[@valu/assert notNil] ${msg}`, 2); } export function is(ob: any, value: T): ob is T { return ob === value; } export function assertIs(ob: any, value: T, msg?: string): asserts ob is T { if (!msg) { msg = `${_stringify(ob)} !== ${_stringify(value)}`; } assert(is(ob, value), `[@valu/assert Value] ${msg}`, 2); } function _stringify(ob: any) { if (ob === null) { return "null"; } return String(ob); } export function assertNotBrowser() { assert( typeof window === "undefined", "This code is not allowed in the browser", 2, ); } /** * Asserts that the given value is not any type */ export function assertNotAny(value: NotAny) {} type IsAny = unknown extends T ? (T extends {} ? T : never) : never; type NotAny = T extends IsAny ? never : T; /** * Assert that the type of the `value` is assignable to the type T */ export function assertType(value: T) {}