@lucaspaganini/value-objects
Version:
TypeScript first validation and class creation library
133 lines • 5.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.VOFloat = void 0;
var utils_1 = require("../utils");
var errors_1 = require("./errors");
var makeIsInSet = function (values) {
var set = new Set(values);
return function (v) { return set.has(v); };
};
var PRECISION_TRIM_SET = ['floor', 'ceil', 'round'];
var isPrecisionTrim = makeIsInSet(PRECISION_TRIM_SET);
/**
* Function to create a floating point number value object constructor.
*
* @param options Customizations for the returned class constructor
* @return Class constructor that accepts a number for instantiation
* and returns that number when {@link VOFloatInstance.valueOf} is called.
*
* @example
* ```typescript
* class MyFloat extends VOFloat() {}
*
* const float1 = new MyFloat(5); // OK
* float1.valueOf(); // 5
*
* const float2 = new MyFloat(5.0); // OK
* float2.valueOf(); // 5
*
* const float3 = new MyFloat(5.5); // OK
* float3.valueOf(); // 5.5
*
* const float4 = new MyFloat('5.5'); // Compilation error: Not a number
* ```
*
* @example
* ```typescript
* class PositiveNumber extends VOFloat({ min: 0 }) {} // OK
* new PositiveNumber(0); // OK
* new PositiveNumber(1000000); // Ok
* new PositiveNumber(-1); // Runtime error: Too small
* new PositiveNumber(1.5); // OK
* ```
*
* @example
* ```typescript
* class FloatWithValidRange extends VOFloat({ min: -100.5, max: 100.5 }) {} // OK
* new FloatWithValidRange(-100); // OK
* new FloatWithValidRange(100); // Ok
* new FloatWithValidRange(-100.5); // OK
* new FloatWithValidRange(-101); // Runtime error: Too small
* new FloatWithValidRange(101); // Runtime error: Too big
* ```
*
* @example
* ```typescript
* class FloatWithInvalidRange extends VOFloat({ min: 100, max: -100 }) {} // Runtime error: Invalid logic (options.min should not be bigger than options.max)
* ```
*
* @example
* ```typescript
* class LimitedPrecisionFloat extends VOFloat({
* precision: 5,
* precisionTrim: 'round'
* }) {} // OK
* const limited1 = new LimitedPrecisionFloat(0.123456789);
* limited1.valueOf(); // 0.12346 => Only 5 precision digits and it's rounded
* ```
*
* @example
* ```typescript
* class LimitedPrecisionFloatWithRange extends VOFloat({
* min: 1,
* max: 999.999,
* precision: 2,
* precisionTrim: 'ceil'
* }) {} // OK
* new LimitedPrecisionFloatWithRange(-100); // Runtime error: Too small
* new LimitedPrecisionFloatWithRange(100); // Ok
* new LimitedPrecisionFloatWithRange(0.9999); // OK (rounds to 1 and passes the minimum)
* new LimitedPrecisionFloatWithRange(999.999); // Runtime error: Too big (rounds to 1000 and doesn't pass the maximum)
* const limited2 = new LimitedPrecisionFloatWithRange(0.123456789);
* limited2.valueOf(); // 0.13 => Only 2 precision digits and it's rounded up because we're using "ceil"
* ```
*/
var VOFloat = function (options) {
var _a, _b;
if (options === void 0) { options = {}; }
if (utils_1.isDefined(options.min)) {
if (utils_1.isNotNumber(options.min))
throw new errors_1.RawTypeError('number', typeof options.min, 'options.min');
}
if (utils_1.isDefined(options.max)) {
if (utils_1.isNotNumber(options.max))
throw new errors_1.RawTypeError('number', typeof options.max, 'options.max');
}
if (utils_1.isDefined(options.min) && utils_1.isDefined(options.max)) {
if (options.min > options.max)
throw new errors_1.LogicError('options.min should not be bigger than options.max');
}
if (utils_1.isDefined(options.precision)) {
if (utils_1.isNotNumber(options.precision))
throw new errors_1.RawTypeError('number', typeof options.precision, 'options.precision');
if (!Number.isInteger(options.precision))
throw new errors_1.NotIntegerError(options.precision, 'options.precision');
if (options.precision < 0)
throw new errors_1.MinSizeError(options.precision, 0);
}
if (utils_1.isDefined(options.precisionTrim)) {
if (!isPrecisionTrim(options.precisionTrim))
throw new errors_1.NotInSetError(PRECISION_TRIM_SET, options.precisionTrim, 'options.precisionTrim');
}
var precisionPower = Math.pow(10, ((_a = options.precision) !== null && _a !== void 0 ? _a : 0));
var precisionTrim = (_b = options.precisionTrim) !== null && _b !== void 0 ? _b : 'round';
return /** @class */ (function () {
function class_1(raw) {
if (utils_1.isNotNumber(raw))
throw new errors_1.RawTypeError('number', typeof raw, 'raw');
if (utils_1.isDefined(options.precision))
raw = Math[precisionTrim](raw * precisionPower) / precisionPower;
if (utils_1.isDefined(options.min) && raw < options.min)
throw new errors_1.MinSizeError(options.min, raw);
if (utils_1.isDefined(options.max) && raw > options.max)
throw new errors_1.MaxSizeError(options.max, raw);
this._value = raw;
}
class_1.prototype.valueOf = function () {
return this._value;
};
return class_1;
}());
};
exports.VOFloat = VOFloat;
//# sourceMappingURL=float.js.map