@dozerg/condition
Version:
Preconditions utility for TypeScript and JavaScript.
280 lines (279 loc) • 8.84 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.assertIsBigint = exports.assertIsBoolean = exports.assertIsString = exports.assertIsNumber = exports.isBigint = exports.isBoolean = exports.isString = exports.isNumber = void 0;
exports.assertTrue = assertTrue;
exports.isNonNull = isNonNull;
exports.assertNonNull = assertNonNull;
exports.isObject = isObject;
exports.isClass = isClass;
exports.assertIsObject = assertIsObject;
exports.assertIsClass = assertIsClass;
/**
* Check if a condition is true, or throw an error with custom message.
* @example
* ```ts
* const a: unknown = 'abc';
* // a.length; // expect a compiler error
*
* assertTrue(typeof a === 'string');
* a.length; // OK, a is string
* ```
*
* @param condition - The condition to be checked
* @param message - Error message, or absent for default message
* @param props - Extra properties to be added to error message
*/
function assertTrue(condition, message, props) {
if (!condition)
throwError(message !== null && message !== void 0 ? message : `Expected true but got ${condition}`, props);
}
/**
* Check if a value is neither `null` nor `undefined`.
* @example
* ```ts
* const a = [1, undefined, 2]; // a is (number | undefined)[]
* const b = a.filter(isNonNull); // b is number[]
* ```
*
* @param value - The value to be checked
* @returns false if the value is `null` or `undefined`, or true otherwise
*/
function isNonNull(value) {
return value !== undefined && value !== null;
}
/**
* Check if a value is neither `null` nor `undefined`, or throw an error with custom message.
* @example
* ```ts
* function f(v?: string) {
* //v.length; // expect a compiler error
* assertIsNonNull(v);
* v.length; // OK, v is string
* }
* ```
*
* @param value - The value to be checked
* @param message - Error message, or absent for default message
* @param props - Extra properties to be added to error message
*/
function assertNonNull(value, message, props) {
if (!isNonNull(value))
throwError(message !== null && message !== void 0 ? message : `Expected non-null value but got ${value}`, props);
}
/**
* Check if a value is number.
* @example
* ```ts
* const a = ['1', 2, '3', 4]; // a is (string | number)[]
* const b = a.filter(isNumber); // b is [2, 4], i.e. number[]
* ```
*
* @param value - The value to be checked
* @returns true if the value is number, or false otherwise
*/
exports.isNumber = isType('number');
/**
* Check if a value is string.
* @example
* ```ts
* const a = ['1', 2, '3', 4]; // a is (string | number)[]
* const b = a.filter(isString); // b is ['1', '3'], i.e. string[]
* ```
*
* @param value - The value to be checked
* @returns true if the value is string, or false otherwise
*/
exports.isString = isType('string');
/**
* Check if a value is boolean.
* @example
* ```ts
* const a = ['1', true, '3', false]; // a is (string | boolean)[]
* const b = a.filter(isBoolean); // b is [true, false], i.e. boolean[]
* ```
*
* @param value - The value to be checked
* @returns true if the value is boolean, or false otherwise
*/
exports.isBoolean = isType('boolean');
/**
* Check if a value is bigint.
* @example
* ```ts
* const a = [1, BigInt(2), 3, BigInt(4)]; // a is (number | bigint)[]
* const b = a.filter(isBigint); // b is [BigInt(2), BigInt(3)], i.e. bigint[]
* ```
*
* @param value - The value to be checked
* @returns true if the value is bigint, or false otherwise
*/
exports.isBigint = isType('bigint');
/**
* Check if a value is an object.
* @param v - The value to be checked
* @returns true if the value is an object, or false otherwise
*/
function isObject(v) {
return typeof v === 'object' && !Array.isArray(v) && v !== null;
}
/**
* Returns a function to check if a value is instance of a class.
* @example
* ```ts
* class A {};
* class B {};
* const a = [new A(), 1, new B()]; // a is (number | A | B)[]
* const b = a.filter(isClass(A)); // b is [new A()], i.e. A[]
* ```
*
* @param Class - The constructor of a class
* @returns A function
*/
function isClass(Class) {
return (value) => {
return value instanceof Class;
};
}
// https://github.com/microsoft/TypeScript/issues/41047#issuecomment-706752079
const _assertIsNumber = assertIsType(exports.isNumber, v => `Expected a number but got ${desc(v)}`);
const _assertIsString = assertIsType(exports.isString, v => `Expected a string but got ${desc(v)}`);
const _assertIsBoolean = assertIsType(exports.isBoolean, v => `Expected a boolean but got ${desc(v)}`);
const _assertIsBigint = assertIsType(exports.isBigint, v => `Expected a bigint but got ${desc(v)}`);
/**
* Check if a value is number, or throw an error with custom message.
* @example
* ```ts
* function f(v: boolean | number) {
* //v + 1; // expect a compiler error
* assertIsNumber(v);
* v + 1; // OK, v is number
* }
* ```
*
* @param value - The value to be checked
* @param message - Error message, or absent for default message
* @param props - Extra properties to be added to error message
*/
exports.assertIsNumber = _assertIsNumber;
/**
* Check if a value is string, or throw an error with custom message.
* @example
* ```ts
* function f(v: boolean | string) {
* //v.length; // expect a compiler error
* assertIsString(v);
* v.length; // OK, v is string
* }
* ```
*
* @param value - The value to be checked
* @param message - Error message, or absent for default message
* @param props - Extra properties to be added to error message
*/
exports.assertIsString = _assertIsString;
/**
* Check if a value is boolean, or throw an error with custom message.
* @example
* ```ts
* function f(v: A) {}
*
* function g(v: boolean | string) {
* // f(v); // expect a compiler error
* assertIsBoolean(v);
* f(v); // OK, v is boolean
* }
* ```
*
* @param value - The value to be checked
* @param message - Error message, or absent for default message
* @param props - Extra properties to be added to error message
*/
exports.assertIsBoolean = _assertIsBoolean;
/**
* Check if a value is bigint, or throw an error with custom message.
* @example
* ```ts
* function f(v: bigint) {}
*
* function g(v: bigint | string) {
* // f(v); // expect a compiler error
* assertIsBigint(v);
* f(v); // OK, v is bigint
* }
* ```
*
* @param value - The value to be checked
* @param message - Error message, or absent for default message
* @param props - Extra properties to be added to error message
*/
exports.assertIsBigint = _assertIsBigint;
/**
* Check if a value is an object, or throw an error with custom message.
*
* @param value - The value to be checked
* @param message - Error message, or absent for default message
* @param props - Extra properties to be added to error message
*/
function assertIsObject(value, message, props) {
if (!isObject(value))
throwError(message !== null && message !== void 0 ? message : `Expect an object but got ${desc(value)}`, props);
}
/**
* Check if a value is instance of a class, or throw an error with custom message.
* @example
* ```ts
* class A {
* a() {}
* }
*
* function f(v: A | string) {
* // v.a(); // expect a compiler error
* assertIsClass(A, v);
* v.a(); // OK, v is class A
* }
* ```
*
* @param value - The value to be checked
* @param message - Error message, or absent for default message
* @param props - Extra properties to be added to error message
*/
function assertIsClass(Class, value, message, props) {
if (!isClass(Class)(value))
throwError(message !== null && message !== void 0 ? message : `Expected class ${Class.name} but got ${desc(value)}`, props);
}
function isType(name) {
return (value) => {
return typeof value === name;
};
}
function assertIsType(check, defaultMsg) {
return (value, message, props) => {
if (!check(value))
throwError(message !== null && message !== void 0 ? message : defaultMsg(value), props);
};
}
function throwError(msg, props) {
const pmsg = props ? `, props = ${JSON.stringify(props)}` : '';
throw Error(msg + pmsg + '.');
}
function desc(v) {
switch (typeof v) {
case 'string':
return `'${v}'`;
case 'object':
if (v === null)
return 'null';
else if (Array.isArray(v))
return JSON.stringify(v);
else {
const { name } = v.constructor;
if (name === 'Object')
return JSON.stringify(v);
return `class ${name}`;
}
case 'function':
return 'Function';
default:
return `${v}`;
}
}