const all = (...preds) => (obj) => preds.map(f => f(obj)).reduce((a, b) => a && b, true) const any = (...preds) => (obj) => preds.map(f => f(obj)).reduce((a, b) => a || b, false) const oneOf = (...preds) => (obj) => preds.map(f => f(obj)).reduce((a, b) => a ? !b : b, false) const has = (prop) => (obj) => obj[prop] !== undefined const not = (pred) => (obj) => !pred(obj) const equals = (prop, val) => (obj) => obj[prop] === val const implies = (f, g) => (obj) => !f(obj) || g(obj); const validate = all(implies(has('selectedIndex'), equals('isOpen', true))) validate({}) // true; passes all 'implications' validate({'selectedIndex': 3}) // false; isOpen !== true! validate({'selectedIndex': 3, isOpen: true}) // true; passes all implications // more complex example const complexValidate = all( implies(equals('mode', 'indexed'), all( has('selectedIndex'), obj => obj['selectedIndex'] <= 5 ) ), implies(equals('mode', 'disabled'), not(has('selectedIndex'))) )