add predicate logic everywhere

This commit is contained in:
Yanick Champoux 2024-02-27 13:16:56 -05:00
parent 068f21f3ca
commit 1c695ab8e1
9 changed files with 30 additions and 21 deletions

View File

@ -357,8 +357,10 @@ expect(alwaysFour(32)).to.eql(4);
### `u.if(dataIn, predicate, updates)` ### `u.if(dataIn, predicate, updates)`
Apply `updates` if `predicate` is truthy, or if `predicate` is a function. Apply `updates` if `predicate` evaluates to true. The `predicate` can
It evaluates to truthy when called with `object`. be a boolean, or a function taking in `dataIn` and returning a boolean,
or an object, in which case it'll be treated as a shortcut for
`u.matches(predicate)`.
```js ```js
function isEven(x) { function isEven(x) {

View File

@ -1,11 +1,12 @@
import { filter as _filter } from "remeda"; import { filter as _filter } from "remeda";
import { buildPredicate } from "./predicate.js";
import wrap from "./wrap.js"; import wrap from "./wrap.js";
const sizeOf = (obj) => obj.length; const sizeOf = (obj) => obj.length;
function filter(dataIn, predicate) { function filter(dataIn, predicate) {
const result = _filter.indexed(dataIn, predicate); const result = _filter.indexed(dataIn, buildPredicate(predicate));
return sizeOf(result) === sizeOf(dataIn) ? dataIn : result; return sizeOf(result) === sizeOf(dataIn) ? dataIn : result;
} }

View File

@ -5,7 +5,7 @@ import _if from "./if.js";
describe("if", () => { describe("if", () => {
test("does not update if the predicate is false", () => { test("does not update if the predicate is false", () => {
const object = { a: 0 }; const object = { a: 0 };
let result = _if(false, { b: 1 }, object); let result = _if(object, false, { b: 1 });
expect(result).to.eql(object); expect(result).to.eql(object);
result = _if(0, false, 1); result = _if(0, false, 1);
@ -21,7 +21,7 @@ describe("if", () => {
test("will use the result of a function passed as a predicate", () => { test("will use the result of a function passed as a predicate", () => {
const object = { a: 0 }; const object = { a: 0 };
const aIsThree = (x) => x.a === 3; const aIsThree = (x) => x.a === 3;
const result = _if(aIsThree, { b: 1 }, object); const result = _if(aIsThree, { b: 1 })(object);
expect(result).to.eql({ a: 0 }); expect(result).to.eql({ a: 0 });
}); });

View File

@ -1,16 +1,15 @@
import update from "./update.js"; import update from "./update.js";
import wrap from "./wrap.js"; import wrap from "./wrap.js";
import { Predicate, buildPredicate } from "./predicate.js";
function updateIfElse(object, predicate, trueUpdates, falseUpdates) { function updateIfElse(object, predicate, trueUpdates, falseUpdates) {
const test = typeof predicate === "function" ? predicate(object) : predicate; const test = buildPredicate(predicate)(object);
const updates = test ? trueUpdates : falseUpdates; const updates = test ? trueUpdates : falseUpdates;
return update(object, updates); return update(object, updates);
} }
type Predicate = ((source: any) => boolean) | boolean;
export interface IfElse { export interface IfElse {
(object, predicate: Predicate, trueUpdates, falseUpdates): unknown; (object, predicate: Predicate, trueUpdates, falseUpdates): unknown;
(predicate: Predicate, trueUpdates, falseUpdates): (unknown) => unknown; (predicate: Predicate, trueUpdates, falseUpdates): (unknown) => unknown;

View File

@ -2,16 +2,10 @@ import wrap from "./wrap.js";
import matches from "./matches.js"; import matches from "./matches.js";
import map from "./map.js"; import map from "./map.js";
import ifElse from "./ifElse.js"; import ifElse from "./ifElse.js";
import { buildPredicate } from "./predicate.js";
function _mapIfElse(object, predicate, trueUpdates, falseUpdates) { function _mapIfElse(object, predicate, trueUpdates, falseUpdates) {
const test = const test = buildPredicate(predicate);
typeof predicate === "function"
? predicate
: typeof predicate === "object"
? matches(predicate)
: predicate;
const updates = test ? trueUpdates : falseUpdates;
return map(object, ifElse(test, trueUpdates, falseUpdates)); return map(object, ifElse(test, trueUpdates, falseUpdates));
} }
@ -20,8 +14,6 @@ function mapIf(object, predicate, trueUpdates) {
return _mapIfElse(object, predicate, trueUpdates, (x) => x); return _mapIfElse(object, predicate, trueUpdates, (x) => x);
} }
type Predicate = ((source: any) => boolean) | boolean | Record<string, any>;
export interface MapIfElse { export interface MapIfElse {
(object, predicate: Predicate, trueUpdates, falseUpdates): unknown; (object, predicate: Predicate, trueUpdates, falseUpdates): unknown;
(predicate: Predicate, trueUpdates, falseUpdates): (unknown) => unknown; (predicate: Predicate, trueUpdates, falseUpdates): (unknown) => unknown;

View File

@ -1,11 +1,12 @@
import { omitBy as _omitBy } from "remeda"; import { omitBy as _omitBy } from "remeda";
import { buildPredicate } from "./predicate.js";
import wrap from "./wrap.js"; import wrap from "./wrap.js";
const sizeOf = (obj) => Object.keys(obj).length; const sizeOf = (obj) => Object.keys(obj).length;
function omitBy(dataIn, predicate) { function omitBy(dataIn, predicate) {
const result = _omitBy(dataIn, predicate); const result = _omitBy(dataIn, buildPredicate(predicate));
return sizeOf(result) === sizeOf(dataIn) ? dataIn : result; return sizeOf(result) === sizeOf(dataIn) ? dataIn : result;
} }

View File

@ -1,11 +1,12 @@
import { pickBy as _pick } from "remeda"; import { pickBy as _pick } from "remeda";
import { buildPredicate } from "./predicate.js";
import wrap from "./wrap.js"; import wrap from "./wrap.js";
const sizeOf = (obj) => Object.keys(obj).length; const sizeOf = (obj) => Object.keys(obj).length;
function pickBy(dataIn, predicate) { function pickBy(dataIn, predicate) {
const result = _pick(dataIn, predicate); const result = _pick(dataIn, buildPredicate(predicate));
return sizeOf(result) === sizeOf(dataIn) ? dataIn : result; return sizeOf(result) === sizeOf(dataIn) ? dataIn : result;
} }

12
src/predicate.ts Normal file
View File

@ -0,0 +1,12 @@
import matches from "./matches.js";
export type Predicate =
| ((source: any) => boolean)
| boolean
| Record<string, any>;
export function buildPredicate(predicate) {
if (typeof predicate === "function") return predicate;
if (typeof predicate === "object") return matches(predicate);
return () => !!predicate;
}

View File

@ -1,11 +1,12 @@
import { reject as _reject } from "remeda"; import { reject as _reject } from "remeda";
import { buildPredicate } from "./predicate.js";
import wrap from "./wrap.js"; import wrap from "./wrap.js";
const sizeOf = (obj) => obj.length; const sizeOf = (obj) => obj.length;
function reject(dataIn, predicate) { function reject(dataIn, predicate) {
const result = _reject.indexed(dataIn, predicate); const result = _reject.indexed(dataIn, buildPredicate(predicate));
return sizeOf(result) === sizeOf(dataIn) ? dataIn : result; return sizeOf(result) === sizeOf(dataIn) ? dataIn : result;
} }