ts-data-forge
Version:
[](https://www.npmjs.com/package/ts-data-forge) [](https://www.npmjs.com/package/ts-data-forge) [ • 8.3 kB
JavaScript
import '../functional/optional.mjs';
import { pipe } from '../functional/pipe.mjs';
import '../functional/result.mjs';
import { Num } from './num.mjs';
/** @internal */
var TsDataForgeInternals;
(function (TsDataForgeInternals) {
(function (RefinedNumberUtils) {
const castTypeImpl = (is, typeNameInErrorMessage) => (a) => {
if (!is(a)) {
throw new TypeError(`Expected ${typeNameInErrorMessage}, got: ${a}`);
}
return a;
};
const isNonZero = (n) => n !== 0;
const isFnOrUndefined = (min, max) => min === undefined
? max === undefined
? undefined
: (n) => n <= max
: max === undefined
? (n) => min <= n
: Num.isInRangeInclusive(min, max);
const clampFnOrUndefined = (min, max) => min === undefined
? max === undefined
? undefined
: (n) => Math.min(max, n)
: max === undefined
? (n) => Math.max(min, n)
: Num.clamp(min, max);
/**
* Factory function that creates a complete set of type-safe operations for integer types.
*
* This function generates:
* - Type guards and validators
* - Arithmetic operations that preserve type constraints
* - Utility functions (min, max, abs, random)
* - Automatic clamping for bounded types
*
* All operations ensure results remain within the type's constraints,
* using clamping when bounds are specified.
*
* @template ElementType - The integer branded type
* @template MIN_VALUE - Optional minimum value for bounded types
* @template MAX_VALUE - Optional maximum value for bounded types
*
* @param config - Configuration object
* @param config.integerOrSafeInteger - Whether to use Number.isInteger or Number.isSafeInteger
* @param config.nonZero - If true, excludes zero from valid values
* @param config.MIN_VALUE - Minimum valid value (inclusive)
* @param config.MAX_VALUE - Maximum valid value (inclusive)
* @param config.typeNameInMessage - Human-readable type name for error messages
*
* @returns Object containing all type-safe operations for the integer type
* @internal
*/
RefinedNumberUtils.operatorsForInteger = ({ integerOrSafeInteger, nonZero, MIN_VALUE, MAX_VALUE, typeNameInMessage, }) => {
const is = (a) => (integerOrSafeInteger === 'Integer'
? Number.isInteger(a)
: Number.isSafeInteger(a)) &&
(nonZero === true ? a !== 0 : true) &&
(isFnOrUndefined(MIN_VALUE, MAX_VALUE)?.(a) ?? true);
const castType = castTypeImpl(is, typeNameInMessage);
const clamp = pipe(clampFnOrUndefined(MIN_VALUE, MAX_VALUE)).mapNullable((cl) => (x) => castType(Math.round(cl(x)))).value;
const clampOrCastFn = clamp ?? castType;
const abs = (x) =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
Math.abs(clampOrCastFn(x));
const min_ = (...values) => clampOrCastFn(Math.min(...values));
const max_ = (...values) => clampOrCastFn(Math.max(...values));
const pow = (x, y) => clampOrCastFn(x ** y);
const add = (x, y) => clampOrCastFn(x + y);
const sub = (x, y) => clampOrCastFn(x - y);
const mul = (x, y) => clampOrCastFn(x * y);
const div = (x, y) => clampOrCastFn(Math.floor(x / y));
const randomImpl = (min = MIN_VALUE, max = MAX_VALUE) => min + Math.floor((Math.max(max, min) - min + 1) * Math.random());
// [-5, 5] -> floor(11 * Math.random()) + (-5)
const random = (min, max) => clampOrCastFn(randomImpl(min, max));
const randomNonZero = (min, max) => {
while (true) {
const r = randomImpl(min, max);
if (Num.isNonZero(r))
return clampOrCastFn(r);
}
};
return {
MIN_VALUE,
MAX_VALUE,
is,
abs,
min: min_,
max: max_,
pow,
add,
sub,
mul,
div,
random,
randomNonZero,
castType,
clamp:
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
clamp,
};
};
/**
* Factory function that creates a complete set of type-safe operations for floating-point types.
*
* This function generates:
* - Type guards and validators (checking for finite values)
* - Arithmetic operations that preserve type constraints
* - Utility functions (min, max, abs, random)
* - Automatic clamping for bounded types
*
* All operations ensure results remain finite and within any specified bounds.
* Division by zero is prevented through type constraints.
*
* @template ElementType - The floating-point branded type
* @template MIN_VALUE - Optional minimum value for bounded types
* @template MAX_VALUE - Optional maximum value for bounded types
*
* @param config - Configuration object
* @param config.nonZero - If true, excludes zero from valid values
* @param config.MIN_VALUE - Minimum valid value (inclusive)
* @param config.MAX_VALUE - Maximum valid value (inclusive)
* @param config.typeNameInMessage - Human-readable type name for error messages
*
* @returns Object containing all type-safe operations for the floating-point type
* @internal
*/
RefinedNumberUtils.operatorsForFloat = ({ nonZero, MIN_VALUE, MAX_VALUE, typeNameInMessage, }) => {
const is = (a) => Number.isFinite(a) &&
(nonZero === true ? a !== 0 : true) &&
(isFnOrUndefined(MIN_VALUE, MAX_VALUE)?.(a) ?? true);
const castType = castTypeImpl(is, typeNameInMessage);
const clamp = pipe(clampFnOrUndefined(MIN_VALUE, MAX_VALUE)).mapNullable((cl) => (x) => castType(cl(x))).value;
const clampOrCastFn = clamp ?? castType;
const abs = (x) =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
Math.abs(x);
const min_ = (...values) => clampOrCastFn(Math.min(...values));
const max_ = (...values) => clampOrCastFn(Math.max(...values));
const pow = (x, y) => clampOrCastFn(x ** y);
const add = (x, y) => clampOrCastFn(x + y);
const sub = (x, y) => clampOrCastFn(x - y);
const mul = (x, y) => clampOrCastFn(x * y);
const div = (x, y) => clampOrCastFn(x / y);
const randomImpl = (min = MIN_VALUE, max = MAX_VALUE) => min + (Math.max(max, min) - min) * Math.random();
const random = (min, max) => clampOrCastFn(randomImpl(min, max));
const randomNonZero = (min, max) => {
while (true) {
const r = random(min, max);
if (isNonZero(r))
return r;
}
};
return {
MIN_VALUE,
MAX_VALUE,
is,
abs,
min: min_,
max: max_,
pow,
add,
sub,
mul,
div,
random,
randomNonZero,
castType,
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
clamp: clamp,
};
};
})(TsDataForgeInternals.RefinedNumberUtils || (TsDataForgeInternals.RefinedNumberUtils = {}));
})(TsDataForgeInternals || (TsDataForgeInternals = {}));
export { TsDataForgeInternals };
//# sourceMappingURL=refined-number-utils.mjs.map