diff --git a/cdn/radash.esm.js b/cdn/radash.esm.js index fefdb319..e3c95293 100644 --- a/cdn/radash.esm.js +++ b/cdn/radash.esm.js @@ -585,6 +585,17 @@ const callable = (obj, fn) => { }); }; +function inRange(number, start, end) { + const isTypeSafe = typeof number === "number" && typeof start === "number" && (typeof end === "undefined" || typeof end === "number"); + if (!isTypeSafe) { + return false; + } + if (typeof end === "undefined") { + end = start; + start = 0; + } + return number >= Math.min(start, end) && number < Math.max(start, end); +} const toFloat = (value, defaultValue) => { const def = defaultValue === void 0 ? 0 : defaultValue; if (value === null || value === void 0) { @@ -923,4 +934,4 @@ const trim = (str, charsToTrim = " ") => { return str.replace(regex, ""); }; -export { all, alphabetical, assign, boil, callable, camel, capitalize, chain, clone, cluster, compose, construct, counting, crush, dash, debounce, defer, diff, draw, first, flat, fork, get, group, guard, intersects, invert, isArray, isDate, isEmpty, isEqual, isFloat, isFunction, isInt, isNumber, isObject, isPrimitive, isPromise, isString, isSymbol, iterate, keys, last, list, listify, lowerize, map, mapEntries, mapKeys, mapValues, max, memo, merge, min, objectify, omit, parallel, partial, partob, pascal, pick, proxied, random, range, reduce, replace, replaceOrAppend, retry, select, series, set, shake, shift, shuffle, sift, sleep, snake, sort, sum, template, throttle, title, toFloat, toInt, toggle, trim, tryit as try, tryit, uid, unique, upperize, zip, zipToObject }; +export { all, alphabetical, assign, boil, callable, camel, capitalize, chain, clone, cluster, compose, construct, counting, crush, dash, debounce, defer, diff, draw, first, flat, fork, get, group, guard, inRange, intersects, invert, isArray, isDate, isEmpty, isEqual, isFloat, isFunction, isInt, isNumber, isObject, isPrimitive, isPromise, isString, isSymbol, iterate, keys, last, list, listify, lowerize, map, mapEntries, mapKeys, mapValues, max, memo, merge, min, objectify, omit, parallel, partial, partob, pascal, pick, proxied, random, range, reduce, replace, replaceOrAppend, retry, select, series, set, shake, shift, shuffle, sift, sleep, snake, sort, sum, template, throttle, title, toFloat, toInt, toggle, trim, tryit as try, tryit, uid, unique, upperize, zip, zipToObject }; diff --git a/cdn/radash.js b/cdn/radash.js index 1ebbe422..e5e27d79 100644 --- a/cdn/radash.js +++ b/cdn/radash.js @@ -588,6 +588,17 @@ var radash = (function (exports) { }); }; + function inRange(number, start, end) { + const isTypeSafe = typeof number === "number" && typeof start === "number" && (typeof end === "undefined" || typeof end === "number"); + if (!isTypeSafe) { + return false; + } + if (typeof end === "undefined") { + end = start; + start = 0; + } + return number >= Math.min(start, end) && number < Math.max(start, end); + } const toFloat = (value, defaultValue) => { const def = defaultValue === void 0 ? 0 : defaultValue; if (value === null || value === void 0) { @@ -951,6 +962,7 @@ var radash = (function (exports) { exports.get = get; exports.group = group; exports.guard = guard; + exports.inRange = inRange; exports.intersects = intersects; exports.invert = invert; exports.isArray = isArray; diff --git a/docs/number/in-range.mdx b/docs/number/in-range.mdx new file mode 100644 index 00000000..d46b25b4 --- /dev/null +++ b/docs/number/in-range.mdx @@ -0,0 +1,22 @@ +--- +title: inRange +description: Checks if the given number is between two numbers. The starting number is inclusive. The ending number is exclusive. The start and the end of the range can be ascending OR descending order. If end is not specified, it's set to start value. And start is set to 0. +group: Number +--- + +## Basic usage + +Pass the number, the start and the end (optional) of the range. The `_.inRange` function will return true if the given number is in the range. + +```ts +import { inRange } from 'radash' + +inRange(10, 0, 20) // true +inRange(9.99, 0, 10) // true +inRange(Math.PI, 0, 3.15) // true +inRange(10, 10, 20) // true +inRange(10, 0, 10) // false + +inRange(1, 2) // true +inRange(1, 0) // false +``` diff --git a/src/index.ts b/src/index.ts index 6c0f6068..9dff2e21 100644 --- a/src/index.ts +++ b/src/index.ts @@ -53,7 +53,7 @@ export { proxied, throttle } from './curry' -export { toFloat, toInt } from './number' +export { inRange, toFloat, toInt } from './number' export { assign, clone, diff --git a/src/number.ts b/src/number.ts index 209ea845..8d7478cf 100644 --- a/src/number.ts +++ b/src/number.ts @@ -1,3 +1,47 @@ +/** + * Checks if the given number is between zero (0) and the ending number. 0 is inclusive. + * + * * Numbers can be negative or positive. + * * Ending number is exclusive. + * + * @param {number} number The number to check. + * @param {number} end The end of the range. Exclusive. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + */ +export function inRange(number: number, end: number): boolean + +/** + * Checks if the given number is between two numbers. + * + * * Numbers can be negative or positive. + * * Starting number is inclusive. + * * Ending number is exclusive. + * * The start and the end of the range can be ascending OR descending order. + * + * @param {number} number The number to check. + * @param {number} start The start of the range. Inclusive. + * @param {number} end The end of the range. Exclusive. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + */ +export function inRange(number: number, start: number, end: number): boolean +export function inRange(number: number, start: number, end?: number): boolean { + const isTypeSafe = + typeof number === 'number' && + typeof start === 'number' && + (typeof end === 'undefined' || typeof end === 'number') + + if (!isTypeSafe) { + return false + } + + if (typeof end === 'undefined') { + end = start + start = 0 + } + + return number >= Math.min(start, end) && number < Math.max(start, end) +} + export const toFloat = ( value: any, defaultValue?: T diff --git a/src/tests/number.test.ts b/src/tests/number.test.ts index d333e88a..ee83dde4 100644 --- a/src/tests/number.test.ts +++ b/src/tests/number.test.ts @@ -2,6 +2,51 @@ import { assert } from 'chai' import * as _ from '..' describe('number module', () => { + describe('inRange function', () => { + test('handles nullish values', () => { + assert.strictEqual(_.inRange(0, 1, null as any), false) + assert.strictEqual(_.inRange(0, null as any, 1), false) + assert.strictEqual(_.inRange(null as any, 0, 1), false) + assert.strictEqual(_.inRange(0, undefined as any, 1), false) + assert.strictEqual(_.inRange(undefined as any, 0, 1), false) + + assert.strictEqual(_.inRange(0, 1, undefined as any), true) + }) + test('handles bad input', () => { + const result = _.inRange(0, 1, {} as any) + assert.strictEqual(result, false) + }) + test('computes correctly', () => { + assert.strictEqual(_.inRange(10, 0, 5), false) + assert.strictEqual(_.inRange(10, 0, 20), true) + assert.strictEqual(_.inRange(-10, 0, -20), true) + assert.strictEqual(_.inRange(9.99, 0, 10), true) + assert.strictEqual(_.inRange(Math.PI, 0, 3.15), true) + }) + test('handles the different syntax of number type', () => { + assert.strictEqual(_.inRange(0, -1, 1), true) + assert.strictEqual(_.inRange(Number(0), -1, 1), true) + assert.strictEqual(_.inRange(+'0', -1, 1), true) + }) + test('handles two params', () => { + assert.strictEqual(_.inRange(1, 2), true) + assert.strictEqual(_.inRange(1.2, 2), true) + assert.strictEqual(_.inRange(2, 1), false) + assert.strictEqual(_.inRange(2, 2), false) + assert.strictEqual(_.inRange(3.2, 2), false) + assert.strictEqual(_.inRange(-1, 1), false) + assert.strictEqual(_.inRange(-1, -10), true) + }) + test('handles the exclusive end of the range', () => { + assert.strictEqual(_.inRange(1, 0, 1), false) + assert.strictEqual(_.inRange(10.0, 0, 10), false) + }) + test('handles the inclusive start of the range', () => { + assert.strictEqual(_.inRange(0, 0, 1), true) + assert.strictEqual(_.inRange(10.0, 10, 20), true) + }) + }) + describe('toFloat function', () => { test('handles null', () => { const result = _.toFloat(null) @@ -24,6 +69,7 @@ describe('number module', () => { assert.strictEqual(result, 20.0) }) }) + describe('toInt function', () => { test('handles null', () => { const result = _.toInt(null)