From 651f434eab5ef135bc17a2ae2f8f1898a5609a3a Mon Sep 17 00:00:00 2001 From: Kodie Grantham Date: Wed, 11 Oct 2017 04:26:45 -0500 Subject: [PATCH] Add is.any() and is.all() methods (#19) --- index.js | 27 +++++++++++++++++++++++++++ readme.md | 24 ++++++++++++++++++++++++ test.js | 30 ++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/index.js b/index.js index a24021c..6f57809 100644 --- a/index.js +++ b/index.js @@ -181,4 +181,31 @@ const isEmptyMapOrSet = x => (is.map(x) || is.set(x)) && x.size === 0; is.empty = x => !x || isEmptyStringOrArray(x) || isEmptyObject(x) || isEmptyMapOrSet(x); +const predicateOnArray = (method, predicate, values) => { + // `values` is the calling function's "arguments object". + // We have to do it this way to keep node v4 support. + // So here we convert it to an array and slice off the first item. + values = Array.prototype.slice.call(values, 1); + + if (is.function(predicate) === false) { + throw new TypeError(`Invalid predicate: ${util.inspect(predicate)}`); + } + + if (values.length === 0) { + throw new TypeError(`Invalid number of values`); + } + + return method.call(values, predicate); +}; + +// We have to use anonymous functions for the any() and all() methods +// to get the arguments since we can't use rest parameters in node v4. +is.any = function (predicate) { + return predicateOnArray(Array.prototype.some, predicate, arguments); +}; + +is.all = function (predicate) { + return predicateOnArray(Array.prototype.every, predicate, arguments); +}; + module.exports = is; diff --git a/readme.md b/readme.md index 0508540..d2e572b 100644 --- a/readme.md +++ b/readme.md @@ -158,6 +158,30 @@ Check if `value` is `Infinity` or `-Infinity`. Returns `true` if `value` is falsy or an empty string, array, object, map, or set. +##### .any(predicate, ...values) + +Returns `true` if **any** of the input `values` returns true in the `predicate`: + +```js +is.any(is.string, {}, true, '🦄'); +//=> true + +is.any(is.boolean, 'unicorns', [], new Map()); +//=> false +``` + +##### .all(predicate, ...values) + +Returns `true` if **all** of the input `values` returns true in the `predicate`: + +```js +is.all(is.object, {}, new Map(), new Set()); +//=> true + +is.all(is.string, '🦄', [], 'unicorns'); +//=> false +``` + ## FAQ ### Why yet another type checking module? diff --git a/test.js b/test.js index c0f3cbf..43566f5 100644 --- a/test.js +++ b/test.js @@ -427,3 +427,33 @@ test('is.empty', t => { tempSet.add(1); t.false(m.empty(tempSet)); }); + +test('is.any', t => { + t.true(m.any(m.string, {}, true, '🦄')); + t.true(m.any(m.object, false, {}, 'unicorns')); + t.false(m.any(m.boolean, '🦄', [], 3)); + t.false(m.any(m.integer, true, 'lol', {})); + + t.throws(() => { + m.any(null, true); + }); + + t.throws(() => { + m.any(m.string); + }); +}); + +test('is.all', t => { + t.true(m.all(m.object, {}, new Set(), new Map())); + t.true(m.all(m.boolean, true, false)); + t.false(m.all(m.string, '🦄', [])); + t.false(m.all(m.set, new Map(), {})); + + t.throws(() => { + m.all(null, true); + }); + + t.throws(() => { + m.all(m.string); + }); +});