every, some, and Includes Patterns
When you need to ask "do all of these match?" or "is there at least one match?", `Array.prototype.every` and `Array.prototype.some` give you boolean answers in one pass. This snippet covers those two plus the count-via-filter pattern for "how many match?" and a small predicate factory pattern that lets you compose these checks for form validation, feature flags, or permission rules.
704 views
10
// every() returns true only if the predicate returns truthy for every item.
const allEven = (arr) => arr.every((n) => n % 2 === 0);
console.log(allEven([2, 4, 6, 8])); // true
console.log(allEven([2, 4, 5, 8])); // false
// At least 10 across the board.
const allAtLeast10 = (arr) => arr.every((n) => n >= 10);
console.log(allAtLeast10([10, 20, 30])); // true
console.log(allAtLeast10([10, 5, 30])); // false
// Form-validation flavor: every required field has a value.
const fields = [
{ name: 'email', value: '[email protected]' },
{ name: 'password', value: 'secret' }
];
console.log(fields.every((f) => f.value.length > 0)); // true
// Empty-array gotcha: every() returns true (vacuous truth).
console.log([].every((n) => n > 100)); // trueevery is the right call when you want a single boolean answer to an all-of question. It short-circuits on the first failure, which makes it cheap on large arrays where mismatches happen early. The empty-array case is the only real gotcha: [].every(predicate) returns true because there is nothing that fails the test. Guard with an explicit arr.length > 0 if you want "at least one item AND all match".
// some() returns true on the first truthy predicate result.
const hasEven = (arr) => arr.some((n) => n % 2 === 0);
console.log(hasEven([1, 3, 5, 8])); // true
console.log(hasEven([1, 3, 5, 7])); // false
// Permission check: any role grants admin?
const roles = ['viewer', 'editor', 'admin'];
console.log(roles.some((r) => r === 'admin')); // true
// some() is the boolean cousin of includes() but accepts a predicate.
// includes() does strict equality + handles NaN.
console.log([1, NaN, 3].includes(NaN)); // true
console.log([1, NaN, 3].some((n) => Number.isNaN(n))); // true (same answer, different shape)
// Empty-array gotcha: some() returns false.
console.log([].some((n) => n > 0)); // falsesome is every's mirror image: it returns true as soon as one item passes and false if none do. It also short-circuits, so on a large array where matches cluster early it is essentially free. Use some when the predicate is non-trivial ((item) => item.role === 'admin' && item.active); use includes when you only need exact-value membership on primitives because it handles NaN correctly while indexOf does not. Empty arrays return false, which is the intuitive opposite of every's true.
// 'How many even numbers?' answered in one expression.
const countWhere = (arr, predicate) => arr.filter(predicate).length;
console.log(countWhere([1, 2, 3, 4, 5, 6], (n) => n % 2 === 0)); // 3
console.log(countWhere(['a', 'bb', 'ccc'], (s) => s.length >= 2)); // 2
// reduce-based counter: same answer, no intermediate array.
const countWhereReduce = (arr, predicate) =>
arr.reduce((sum, item) => sum + (predicate(item) ? 1 : 0), 0);
console.log(countWhereReduce([1, 2, 3, 4, 5, 6], (n) => n % 2 === 0)); // 3filter(predicate).length is the readable answer for "how many items match?" The cost is one allocation for the intermediate array, which is fine for almost everything. For very large arrays or a tight loop, the reduce form sums booleans without allocating. Both are linear time. Note that this is a strict count, not a boolean; if you only need to know "at least one" or "none", reach for some or every from the previous accordions because they short-circuit and skip the rest of the array.
// Reusable predicates as small functions.
const isEven = (n) => n % 2 === 0;
const atLeast = (threshold) => (n) => n >= threshold;
const withTag = (tag) => (item) => item.tags?.includes(tag);
console.log([1, 2, 3, 4].every(isEven)); // false
console.log([2, 4, 6].every(isEven)); // true
console.log([10, 20, 30].every(atLeast(10))); // true
console.log([10, 5, 30].every(atLeast(10))); // false
// Combine for richer rules.
const posts = [
{ id: 1, tags: ['js', 'web'] },
{ id: 2, tags: ['js'] }
];
console.log(posts.every(withTag('js'))); // true
console.log(posts.some(withTag('web'))); // true
console.log(posts.every(withTag('web'))); // false
// AND combinator over multiple predicates.
const all = (...preds) => (x) => preds.every((p) => p(x));
console.log([12, 14, 16].every(all(isEven, atLeast(10)))); // trueNaming predicates lets you read arr.every(isEven) instead of decoding an inline arrow at the call site, and predicate factories like atLeast(10) capture parameters in a closure so the call site stays clean. Combinators like all(...preds) (logical AND) and a similar any (logical OR) compose without changing how the underlying every/some work. This is the same pattern Lodash exposes through _.overEvery and _.overSome, but it is small enough to write by hand and it keeps your validation rules and permission checks readable.
