addAdds two numbers.
Data First
P.add(value, addend);
P.add(10, 5); // => 15
P.add(10, -5); // => 5
P.reduce([1, 2, 3, 4], P.add, 0); // => 10
valueThe number.addendThe number to add to the value.bigintData Last
P.add(addend)(value);
P.add(5)(10); // => 15
P.add(-5)(10); // => 5
P.map([1, 2, 3, 4], P.add(1)); // => [2, 3, 4, 5]
addendThe number to add to the value.ObjectaddPropAdd a new property to an object.
The function doesn't do any checks on the input object. If the property already exists it will be overwritten, and the type of the new value is not checked against the previous type.
Use set to override values explicitly with better protections.
Data First
P.addProp(obj, prop, value);
P.addProp({ firstName: 'john' }, 'lastName', 'doe'); // => {firstName: 'john', lastName: 'doe'}
objthe target objectpropthe property namevaluethe property valueObjectData Last
P.addProp(prop, value)(obj);
P.addProp('lastName', 'doe')({ firstName: 'john' }); // => {firstName: 'john', lastName: 'doe'}
propthe property namevaluethe property valueObjectallPassDetermines whether all predicates returns true for the input data.
Data First
P.allPass(data, fns);
const isDivisibleBy3 = (x: number) => x % 3 === 0;
const isDivisibleBy4 = (x: number) => x % 4 === 0;
const fns = [isDivisibleBy3, isDivisibleBy4];
P.allPass(12, fns); // => true
P.allPass(8, fns); // => false
dataThe input data for predicates.fnsThe list of predicates.booleanData Last
P.allPass(fns)(data);
const isDivisibleBy3 = (x: number) => x % 3 === 0;
const isDivisibleBy4 = (x: number) => x % 4 === 0;
const fns = [isDivisibleBy3, isDivisibleBy4];
P.allPass(fns)(12); // => true
P.allPass(fns)(8); // => false
fnsThe list of predicates.ObjectanyPassDetermines whether any predicate returns true for the input data.
Data First
P.anyPass(data, fns);
const isDivisibleBy3 = (x: number) => x % 3 === 0;
const isDivisibleBy4 = (x: number) => x % 4 === 0;
const fns = [isDivisibleBy3, isDivisibleBy4];
P.anyPass(8, fns); // => true
P.anyPass(11, fns); // => false
dataThe input data for predicates.fnsThe list of predicates.booleanData Last
P.anyPass(fns)(data);
const isDivisibleBy3 = (x: number) => x % 3 === 0;
const isDivisibleBy4 = (x: number) => x % 4 === 0;
const fns = [isDivisibleBy3, isDivisibleBy4];
P.anyPass(fns)(8); // => true
P.anyPass(fns)(11); // => false
fnsThe list of predicates.ObjectceilRounds up a given number to a specific precision.
If you'd like to round up to an integer (i.e. use this function with constant precision === 0),
use Math.ceil instead, as it won't incur the additional library overhead.
Data First
P.ceil(value, precision);
P.ceil(123.9876, 3); // => 123.988
P.ceil(483.22243, 1); // => 483.3
P.ceil(8541, -1); // => 8550
P.ceil(456789, -3); // => 457000
valueThe number to round up.precisionThe precision to round up to. Must be an integer between -15 and 15.numberData Last
P.ceil(precision)(value);
P.ceil(3)(123.9876); // => 123.988
P.ceil(1)(483.22243); // => 483.3
P.ceil(-1)(8541); // => 8550
P.ceil(-3)(456789); // => 457000
precisionThe precision to round up to. Must be an integer between -15 and 15.ObjectchunkSplit an array into groups the length of size. If array can't be split evenly, the final chunk will be the remaining elements.
Data First
P.chunk(array, size);
P.chunk(['a', 'b', 'c', 'd'], 2); // => [['a', 'b'], ['c', 'd']]
P.chunk(['a', 'b', 'c', 'd'], 3); // => [['a', 'b', 'c'], ['d']]
arrayThe array.sizeThe length of the chunk.ObjectData Last
P.chunk(size)(array);
P.chunk(2)(['a', 'b', 'c', 'd']); // => [['a', 'b'], ['c', 'd']]
P.chunk(3)(['a', 'b', 'c', 'd']); // => [['a', 'b', 'c'], ['d']]
sizeThe length of the chunk.ObjectclampClamp the given value within the inclusive min and max bounds.
Data First
P.clamp(value, { min, max });
clamp(10, { min: 20 }); // => 20
clamp(10, { max: 5 }); // => 5
clamp(10, { max: 20, min: 5 }); // => 10
valueThe number.limitsThe bounds limits.numberData Last
P.clamp({ min, max })(value);
clamp({ min: 20 })(10); // => 20
clamp({ max: 5 })(10); // => 5
clamp({ max: 20, min: 5 })(10); // => 10
limitsThe bounds limits.ObjectcloneCreates a deep copy of the value. Supported types: plain objects,
Array, number, string, boolean, Date, and RegExp. Functions are
assigned by reference rather than copied. Class instances or any other
built-in type that isn't mentioned above are not supported (but might
work).
Data First
P.clone(data);
P.clone({ foo: 'bar' }); // {foo: 'bar'}
dataThe object to clone.ObjectData Last
P.clone()(data);
P.pipe({ foo: 'bar' }, P.clone()); // {foo: 'bar'}
ObjectconcatMerge two or more arrays. This method does not change the existing arrays, but instead returns a new array, even if the other array is empty.
Data First
P.concat(data, other);
P.concat([1, 2, 3], ['a']); // [1, 2, 3, 'a']
dataThe first items, these would be at the beginning of the new
array.otherThe remaining items, these would be at the end of the new
array.ObjectData Last
P.concat(arr2)(arr1);
P.concat(['a'])([1, 2, 3]); // [1, 2, 3, 'a']
otherThe remaining items, these would be at the end of the new
array.ObjectconditionalExecutes a transformer function based on the first matching predicate,
functioning like a series of if...else if... statements. It sequentially
evaluates each case and, upon finding a truthy predicate, runs the
corresponding transformer, and returns, ignoring any further cases, even if
they would match.
!IMPORTANT! - Unlike similar implementations in frameworks like Lodash and
Ramda, this implementation does NOT return a default/fallback
undefined value when none of the cases match; and instead will throw an
exception in those cases.
To add a default case use the conditional.defaultCase helper as the final
case of your implementation. By default it returns undefined, but could be
provided a transformer in order to return something else.
Due to TypeScript's inability to infer the result of negating a type-
predicate we can't refine the types used in subsequent cases based on
previous conditions. Using a switch (true) statement or ternary operators
is recommended for more precise type control when such type narrowing is
needed.
Data Last
P.conditional(...cases)(data);
const nameOrId = 3 as string | number;
P.pipe(
nameOrId,
P.conditional(
[P.isString, (name) => `Hello ${name}`],
[P.isNumber, (id) => `Hello ID: ${id}`],
P.conditional.defaultCase(
(something) => `Hello something (${JSON.stringify(something)})`,
),
),
); //=> 'Hello ID: 3'
case0case1case2case3case4case5case6case7case8case9ObjectData First
P.conditional(data, ...cases);
const nameOrId = 3 as string | number;
P.conditional(
nameOrId,
[P.isString, (name) => `Hello ${name}`],
[P.isNumber, (id) => `Hello ID: ${id}`],
P.conditional.defaultCase(
(something) => `Hello something (${JSON.stringify(something)})`,
),
); //=> 'Hello ID: 3'
dataThe input data to be evaluated against the provided cases.case0case1case2case3case4case5case6case7case8case9ObjectconstantA function that takes any arguments and returns the provided value on every
invocation. This is useful to provide trivial implementations for APIs or in
combination with a ternary or other conditional execution to allow to short-
circuit more complex implementations for a specific case.
Notice that this is a dataLast impl where the function needs to be invoked to get the "do nothing" function.
See also:
doNothing - A function that doesn't return anything.
identity - A function that returns the first argument it receives.
Data Last
P.constant(value);
P.map([1, 2, 3], P.constant('a')); // => ['a', 'a', 'a']
P.map([1, 2, 3], isDemoMode ? P.add(1) : P.constant(0)); // => [2, 3, 4] or [0, 0, 0]
valueThe constant value that would be returned on every invocation.
The value is not copied/cloned on every invocation so care should be taken
with mutable objects (like arrays, objects, Maps, etc...).ObjectcountByCategorize and count elements in an array using a defined callback function. The callback function is applied to each element in the array to determine its category and then counts how many elements fall into each category.
Data First
P.countBy(data, categorizationFn);
P.countBy(['a', 'b', 'c', 'B', 'A', 'a'], toLowerCase); //=> { a: 3, b: 2, c: 1 }
dataThe array.categorizationFnThe categorization function.ObjectData Last
P.countBy(categorizationFn)(data);
P.pipe(['a', 'b', 'c', 'B', 'A', 'a'], P.countBy(toLowerCase)); //=> { a: 3, b: 2, c: 1 }
categorizationFnThe categorization function.ObjectcurryCreates a function with dataFirst and dataLast signatures.
curry is a dynamic function and it's not type safe. It should be wrapped by
a function that have proper typings. Refer to the example below for correct
usage.
!IMPORTANT: functions that simply call curry and return the result (like
almost all functions in this library) should return unknown themselves if
an explicit return type is required. This is because we currently don't
provide a generic return type that is built from the input function, and
crafting one manually isn't worthwhile as we rely on function declaration
overloading to combine the types for dataFirst and dataLast invocations!
P.curry(fn, args);
function _findIndex(array, fn) {
for (let i = 0; i < array.length; i++) {
if (fn(array[i])) {
return i;
}
}
return -1;
}
// data-first
function findIndex<T>(array: T[], fn: (item: T) => boolean): number;
// data-last
function findIndex<T>(fn: (item: T) => boolean): (array: T[]) => number;
function findIndex(...args: unknown[]) {
return P.curry(_findIndex, args);
}
fnThe function to curry.argsThe arguments.lazyA lazy version of the function to curry.unknowndebounceWraps func with a debouncer object that "debounces" (delays) invocations of the function during a defined cool-down period (waitMs). It can be configured to invoke the function either at the start of the cool-down period, the end of it, or at both ends (timing).
It can also be configured to allow invocations during the cool-down period (maxWaitMs).
It stores the latest call's arguments so they could be used at the end of the cool-down period when invoking func (if configured to invoke the function at the end of the cool-down period).
It stores the value returned by func whenever its invoked. This value is returned on every call, and is accessible via the cachedValue property of the debouncer. Its important to note that the value might be different from the value that would be returned from running func with the current arguments as it is a cached value from a previous invocation.
Important: The cool-down period defines the minimum between two invocations, and not the maximum. The period will be extended each time a call is made until a full cool-down period has elapsed without any additional calls.
Data First
P.debounce(func, options);
const debouncer = debounce(identity(), { timing: 'trailing', waitMs: 1000 });
const result1 = debouncer.call(1); // => undefined
const result2 = debouncer.call(2); // => undefined
// after 1 second
const result3 = debouncer.call(3); // => 2
// after 1 second
debouncer.cachedValue; // => 3
funcThe function to debounce, the returned `call` function will have
the exact same signature.optionsAn object allowing further customization of the debouncer:
- `timing?: 'leading' | 'trailing' |'both'`. The default is `'trailing'`.
`leading` would result in the function being invoked at the start of the
cool-down period; `trailing` would result in the function being invoked at
the end of the cool-down period (using the args from the last call to the
debouncer). When `both` is selected the `trailing` invocation would only
take place if there were more than one call to the debouncer during the
cool-down period. **DEFAULT: 'trailing'**
- `waitMs?: number`. The length of the cool-down period in milliseconds. The
debouncer would wait until this amount of time has passed without **any**
additional calls to the debouncer before triggering the end-of-cool-down-
period event. When this happens, the function would be invoked (if `timing`
isn't `'leading'`) and the debouncer state would be reset. **DEFAULT: 0**
- `maxWaitMs?: number`. The length of time since a debounced call (a call
that the debouncer prevented from being invoked) was made until it would be
invoked. Because the debouncer can be continually triggered and thus never
reach the end of the cool-down period, this allows the function to still
be invoked occasionally. IMPORTANT: This param is ignored when `timing` is
`'leading'`.ObjectdifferenceExcludes the values from other array. The output maintains the same order
as the input. The inputs are treated as multi-sets/bags (multiple copies of
items are treated as unique items).
Data First
P.difference(data, other);
P.difference([1, 2, 3, 4], [2, 5, 3]); // => [1, 4]
P.difference([1, 1, 2, 2], [1]); // => [1, 2, 2]
dataThe input items.otherThe values to exclude.ArrayData First
P.difference(other)(data);
P.pipe([1, 2, 3, 4], P.difference([2, 5, 3])); // => [1, 4]
P.pipe([1, 1, 2, 2], P.difference([1])); // => [1, 2, 2]
otherThe values to exclude.ObjectdifferenceWithExcludes the values from other array.
Elements are compared by custom comparator isEquals.
Data First
P.differenceWith(array, other, isEquals);
P.differenceWith(
[{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }],
[{ a: 2 }, { a: 5 }, { a: 3 }],
P.equals,
); // => [{a: 1}, {a: 4}]
arrayThe source array.otherThe values to exclude.isEqualsThe comparator.ArrayData Last
P.differenceWith(other, isEquals)(array);
P.differenceWith(
[{ a: 2 }, { a: 5 }, { a: 3 }],
P.equals,
)([{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }]); // => [{a: 1}, {a: 4}]
P.pipe(
[{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }, { a: 5 }, { a: 6 }], // only 4 iterations
P.differenceWith([{ a: 2 }, { a: 3 }], P.equals),
P.take(2),
); // => [{a: 1}, {a: 4}]
otherThe values to exclude.isEqualsThe comparator.ObjectdivideDivides two numbers.
Data First
P.divide(value, divisor);
P.divide(12, 3); // => 4
P.reduce([1, 2, 3, 4], P.divide, 24); // => 1
valueThe number.divisorThe number to divide the value by.bigintData Last
P.divide(divisor)(value);
P.divide(3)(12); // => 4
P.map([2, 4, 6, 8], P.divide(2)); // => [1, 2, 3, 4]
divisorThe number to divide the value by.ObjectdoNothingA function that takes any arguments and does nothing with them. This is useful as a placeholder for any function or API that requires a void function (a function that doesn't return a value). This could also be used in combination with a ternary or other conditional execution to allow disabling a function call for a specific case.
Notice that this is a dataLast impl where the function needs to be invoked to get the "do nothing" function.
See also:
constant - A function that ignores it's arguments and returns the same value on every invocation.
identity - A function that returns the first argument it receives.
Data Last
P.doNothing();
myApi({ onSuccess: handleSuccess, onError: P.doNothing() });
myApi({ onSuccess: isDemoMode ? P.doNothing() : handleSuccess });
ObjectdropRemoves first n elements from the array.
Data First
P.drop(array, n);
P.drop([1, 2, 3, 4, 5], 2); // => [3, 4, 5]
arrayThe target array.nThe number of elements to skip.ObjectData Last
P.drop(n)(array);
P.drop(2)([1, 2, 3, 4, 5]); // => [3, 4, 5]
nThe number of elements to skip.ObjectdropFirstByDrop the first n items from data based on the provided ordering criteria. This allows you to avoid sorting the array before dropping the items. The complexity of this function is O(Nlogn) where N is the length of the array.
For the opposite operation (to keep n elements) see takeFirstBy.
Data First
P.dropFirstBy(data, n, ...rules);
P.dropFirstBy(['aa', 'aaaa', 'a', 'aaa'], 2, (x) => x.length); // => ['aaa', 'aaaa']
dataThe input array.nThe number of items to drop. If `n` is non-positive no items would be dropped and a *clone* of the input would be returned, if `n` is bigger then data.length no items would be returned.rulesA variadic array of order rules defining the sorting criteria. Each order rule is a projection function that extracts a comparable value from the data. Sorting is based on these extracted values using the native `<` and `>` operators. Earlier rules take precedence over later ones. Use the syntax `[projection, "desc"]` for descending order.ArrayData Last
P.dropFirstBy(n, ...rules)(data);
P.pipe(
['aa', 'aaaa', 'a', 'aaa'],
P.dropFirstBy(2, (x) => x.length),
); // => ['aaa', 'aaaa']
nThe number of items to drop. If `n` is non-positive no items would be dropped and a *clone* of the input would be returned, if `n` is bigger then data.length no items would be returned.rulesA variadic array of order rules defining the sorting criteria. Each order rule is a projection function that extracts a comparable value from the data. Sorting is based on these extracted values using the native `<` and `>` operators. Earlier rules take precedence over later ones. Use the syntax `[projection, "desc"]` for descending order.ObjectdropLastRemoves last n elements from the array.
Data First
P.dropLast(array, n);
P.dropLast([1, 2, 3, 4, 5], 2); // => [1, 2, 3]
arrayThe target array.nThe number of elements to skip.ArrayData Last
P.dropLast(n)(array);
P.dropLast(2)([1, 2, 3, 4, 5]); // => [1, 2, 3]
nThe number of elements to skip.ObjectdropLastWhileRemoves elements from the end of the array until the predicate returns false.
The predicate is applied to each element in the array starting from the end and moving towards the beginning, until the predicate returns false. The returned array includes elements from the beginning of the array, up to and including the element that produced false for the predicate.
Data First
P.dropLastWhile(data, predicate);
P.dropLastWhile([1, 2, 10, 3, 4], (x) => x < 10); // => [1, 2, 10]
dataThe array.predicateThe predicate.ArrayData Last
P.dropLastWhile(predicate)(data);
P.pipe(
[1, 2, 10, 3, 4],
P.dropLastWhile((x) => x < 10),
); // => [1, 2, 10]
predicateThe predicate.ObjectdropWhileRemoves elements from the beginning of the array until the predicate returns false.
The predicate is applied to each element in the array, until the predicate returns false. The returned array includes the rest of the elements, starting with the element that produced false for the predicate.
Data First
P.dropWhile(data, predicate);
P.dropWhile([1, 2, 10, 3, 4], (x) => x < 10); // => [10, 3, 4]
dataThe array.predicateThe predicate.ArrayData Last
P.dropWhile(predicate)(data);
P.pipe(
[1, 2, 10, 3, 4],
P.dropWhile((x) => x < 10),
); // => [10, 3, 4]
predicateThe predicate.ObjectentriesReturns an array of key/values of the enumerable properties of an object.
Data First
P.entries(object);
P.entries({ a: 1, b: 2, c: 3 }); // => [['a', 1], ['b', 2], ['c', 3]]
dataObject to return keys and values of.ArrayData Last
P.entries()(object);
P.pipe({ a: 1, b: 2, c: 3 }, P.entries()); // => [['a', 1], ['b', 2], ['c', 3]]
ObjectevolveCreates a new object by applying functions that is included in evolver object parameter
to the data object parameter according to their corresponding path.
Functions included in evolver object will not be invoked
if its corresponding key does not exist in the data object.
Also, values included in data object will be kept as is
if its corresponding key does not exist in the evolver object.
Data First
P.evolve(data, evolver);
const evolver = {
count: add(1),
time: { elapsed: add(1), remaining: add(-1) },
};
const data = {
id: 10,
count: 10,
time: { elapsed: 100, remaining: 1400 },
};
evolve(data, evolver);
// => {
// id: 10,
// count: 11,
// time: { elapsed: 101, remaining: 1399 },
// }
objectObject whose value is applied to the corresponding function
that is defined in `evolver` at the same path.evolverObject that include functions that is applied to
the corresponding value of `data` object at the same path.ObjectData Last
P.evolve(evolver)(data);
const evolver = {
count: add(1),
time: { elapsed: add(1), remaining: add(-1) },
};
const data = {
id: 10,
count: 10,
time: { elapsed: 100, remaining: 1400 },
};
P.pipe(object, P.evolve(evolver));
// => {
// id: 10,
// count: 11,
// time: { elapsed: 101, remaining: 1399 },
// }
evolverObject that include functions that is applied to
the corresponding value of `data` object at the same path.ObjectfilterCreates a shallow copy of a portion of a given array, filtered down to just
the elements from the given array that pass the test implemented by the
provided function. Equivalent to Array.prototype.filter.
Data First
P.filter(data, predicate);
P.filter([1, 2, 3], (x) => x % 2 === 1); // => [1, 3]
dataThe array to filter.predicateA function to execute for each element in the array. It
should return `true` to keep the element in the resulting array, and `false`
otherwise. A type-predicate can also be used to narrow the result.ArrayData Last
P.filter(predicate)(data);
P.pipe(
[1, 2, 3],
P.filter((x) => x % 2 === 1),
); // => [1, 3]
predicateA function to execute for each element in the array. It
should return `true` to keep the element in the resulting array, and `false`
otherwise.ObjectfindReturns the first element in the provided array that satisfies the provided
testing function. If no values satisfy the testing function, undefined is
returned.
Similar functions:
findLast - If you need the last element that satisfies the provided testing function.
findIndex - If you need the index of the found element in the array.
indexOf - If you need to find the index of a value.
includes - If you need to find if a value exists in an array.
some - If you need to find if any element satisfies the provided testing function.
filter - If you need to find all elements that satisfy the provided testing function.
Data First
P.find(data, predicate);
P.find([1, 3, 4, 6], (n) => n % 2 === 0); // => 4
dataThe items to search in.predicateA function to execute for each element in the array. It
should return `true` to indicate a matching element has been found, and
`false` otherwise. A type-predicate can also be used to narrow the result.ObjectData Last
P.find(predicate)(data);
P.pipe(
[1, 3, 4, 6],
P.find((n) => n % 2 === 0),
); // => 4
predicateA function to execute for each element in the array. It
should return `true` to indicate a matching element has been found, and
`false` otherwise. A type-predicate can also be used to narrow the result.ObjectfindIndexReturns the index of the first element in an array that satisfies the provided testing function. If no elements satisfy the testing function, -1 is returned.
See also the find method, which returns the first element that satisfies
the testing function (rather than its index).
Data First
P.findIndex(data, predicate);
P.findIndex([1, 3, 4, 6], (n) => n % 2 === 0); // => 2
dataThe items to search in.predicateA function to execute for each element in the array. It
should return a `true` to indicate a matching element has been found, and a
`false` otherwise.numberData Last
P.findIndex(predicate)(data);
P.pipe(
[1, 3, 4, 6],
P.findIndex((n) => n % 2 === 0),
); // => 2
predicateA function to execute for each element in the array. It
should return a `true` to indicate a matching element has been found, and a
`false` otherwise.ObjectfindLastIterates the array in reverse order and returns the value of the first element that satisfies the provided testing function. If no elements satisfy the testing function, undefined is returned.
Similar functions:
find - If you need the first element that satisfies the provided testing function.
findLastIndex - If you need the index of the found element in the array.
lastIndexOf - If you need to find the index of a value.
includes - If you need to find if a value exists in an array.
some - If you need to find if any element satisfies the provided testing function.
filter - If you need to find all elements that satisfy the provided testing function.
Data First
P.findLast(data, predicate);
P.findLast([1, 3, 4, 6], (n) => n % 2 === 1); // => 3
dataThe items to search in.predicateA function to execute for each element in the array. It
should return `true` to indicate a matching element has been found, and
`false` otherwise. A type-predicate can also be used to narrow the result.ObjectData Last
P.findLast(predicate)(data);
P.pipe(
[1, 3, 4, 6],
P.findLast((n) => n % 2 === 1),
); // => 3
predicateA function to execute for each element in the array. It
should return `true` to indicate a matching element has been found, and
`false` otherwise. A type-predicate can also be used to narrow the result.ObjectfindLastIndexIterates the array in reverse order and returns the index of the first element that satisfies the provided testing function. If no elements satisfy the testing function, -1 is returned.
See also findLast which returns the value of last element that satisfies
the testing function (rather than its index).
Data First
P.findLastIndex(data, predicate);
P.findLastIndex([1, 3, 4, 6], (n) => n % 2 === 1); // => 1
dataThe items to search in.predicateA function to execute for each element in the array. It
should return `true` to indicate a matching element has been found, and
`false` otherwise.numberData Last
P.findLastIndex(fn)(items);
P.pipe(
[1, 3, 4, 6],
P.findLastIndex((n) => n % 2 === 1),
); // => 1
predicateA function to execute for each element in the array. It
should return `true` to indicate a matching element has been found, and
`false` otherwise.ObjectfirstGets the first element of array.
Data First
P.first(array);
P.first([1, 2, 3]); // => 1
P.first([]); // => undefined
dataThe array.ObjectData Last
P.first()(array);
P.pipe(
[1, 2, 4, 8, 16],
P.filter((x) => x > 3),
P.first(),
(x) => x + 1,
); // => 5
ObjectfirstByFind the first element in the array that adheres to the order rules provided. This is a superset of what a typical maxBy or minBy function would do as it allows defining "tie-breaker" rules when values are equal, and allows comparing items using any logic. This function is equivalent to calling P.first(P.sortBy(...)) but runs at O(n) instead of O(nlogn).
Use nthBy if you need an element other that the first, or takeFirstBy if you more than just the first element.
Data Last
P.firstBy(...rules)(data);
const max = P.pipe([1, 2, 3], P.firstBy([P.identity(), 'desc'])); // => 3;
const min = P.pipe([1, 2, 3], P.firstBy(P.identity())); // => 1;
const data = [{ a: 'a' }, { a: 'aa' }, { a: 'aaa' }] as const;
const maxBy = P.pipe(data, P.firstBy([(item) => item.a.length, 'desc'])); // => { a: "aaa" };
const minBy = P.pipe(
data,
P.firstBy((item) => item.a.length),
); // => { a: "a" };
const data = [
{ type: 'cat', size: 1 },
{ type: 'cat', size: 2 },
{ type: 'dog', size: 3 },
] as const;
const multi = P.pipe(data, P.firstBy(P.prop('type'), [P.prop('size'), 'desc'])); // => {type: "cat", size: 2}
rulesA variadic array of order rules defining the sorting criteria. Each order rule is a projection function that extracts a comparable value from the data. Sorting is based on these extracted values using the native `<` and `>` operators. Earlier rules take precedence over later ones. Use the syntax `[projection, "desc"]` for descending order.ObjectData First
P.firstBy(data, ...rules);
const max = P.firstBy([1, 2, 3], [P.identity(), 'desc']); // => 3;
const min = P.firstBy([1, 2, 3], P.identity()); // => 1;
const data = [{ a: 'a' }, { a: 'aa' }, { a: 'aaa' }] as const;
const maxBy = P.firstBy(data, [(item) => item.a.length, 'desc']); // => { a: "aaa" };
const minBy = P.firstBy(data, (item) => item.a.length); // => { a: "a" };
const data = [
{ type: 'cat', size: 1 },
{ type: 'cat', size: 2 },
{ type: 'dog', size: 3 },
] as const;
const multi = P.firstBy(data, P.prop('type'), [P.prop('size'), 'desc']); // => {type: "cat", size: 2}
dataAn array of items.rulesA variadic array of order rules defining the sorting criteria. Each order rule is a projection function that extracts a comparable value from the data. Sorting is based on these extracted values using the native `<` and `>` operators. Earlier rules take precedence over later ones. Use the syntax `[projection, "desc"]` for descending order.ObjectflatCreates a new array with all sub-array elements concatenated into it
recursively up to the specified depth. Equivalent to the built-in
Array.prototype.flat method.
Data First
P.flat(data);
P.flat(data, depth);
P.flat([[1, 2], [3, 4], [5], [[6]]]); // => [1, 2, 3, 4, 5, [6]]
P.flat([[[1]], [[2]]], 2); // => [1, 2]
dataThe items to flatten.depthThe depth level specifying how deep a nested array structure
should be flattened. Defaults to 1. Non literal values (those typed as
`number`cannot be used. `Infinity`, `Number.POSITIVE_INFINITY` and
`Number.MAX_VALUE` are all typed as `number` and can't be used either. For
"unlimited" depth use a literal value that would exceed your expected
practical maximum nesting level.ObjectData Last
P.flat()(data);
P.flat(depth)(data);
P.pipe([[1, 2], [3, 4], [5], [[6]]], P.flat()); // => [1, 2, 3, 4, 5, [6]]
P.pipe([[[1]], [[2]]], P.flat(2)); // => [1, 2]
depthThe depth level specifying how deep a nested array structure
should be flattened. Defaults to 1.ObjectflatMapReturns a new array formed by applying a given callback function to each
element of the array, and then flattening the result by one level. It is
identical to a map followed by a flat of depth 1
(flat(map(data, ...args))), but slightly more efficient than calling those
two methods separately. Equivalent to Array.prototype.flatMap.
Data First
P.flatMap(data, callbackfn);
P.flatMap([1, 2, 3], (x) => [x, x * 10]); // => [1, 10, 2, 20, 3, 30]
dataThe items to map and flatten.callbackfnA function to execute for each element in the array. It
should return an array containing new elements of the new array, or a single
non-array value to be added to the new array.ArrayData Last
P.flatMap(callbackfn)(data);
P.pipe(
[1, 2, 3],
P.flatMap((x) => [x, x * 10]),
); // => [1, 10, 2, 20, 3, 30]
callbackfnA function to execute for each element in the array. It
should return an array containing new elements of the new array, or a single
non-array value to be added to the new array.ObjectfloorRounds down a given number to a specific precision.
If you'd like to round down to an integer (i.e. use this function with constant precision === 0),
use Math.floor instead, as it won't incur the additional library overhead.
Data First
P.floor(value, precision);
P.floor(123.9876, 3); // => 123.987
P.floor(483.22243, 1); // => 483.2
P.floor(8541, -1); // => 8540
P.floor(456789, -3); // => 456000
valueThe number to round down.precisionThe precision to round down to. Must be an integer between -15 and 15.numberData Last
P.floor(precision)(value);
P.floor(3)(123.9876); // => 123.987
P.floor(1)(483.22243); // => 483.2
P.floor(-1)(8541); // => 8540
P.floor(-3)(456789); // => 456000
precisionThe precision to round down to. Must be an integer between -15 and 15.ObjectforEachExecutes a provided function once for each array element. Equivalent to
Array.prototype.forEach.
The dataLast version returns the original array (instead of not returning
anything (void)) to allow using it in a pipe. When not used in a pipe the
returned array is equal to the input array (by reference), and not a shallow
copy of it!
Data First
P.forEach(data, callbackfn);
P.forEach([1, 2, 3], (x) => {
console.log(x);
});
dataThe values that would be iterated on.callbackfnA function to execute for each element in the array.voidData Last
P.forEach(callbackfn)(data);
P.pipe(
[1, 2, 3],
P.forEach((x) => {
console.log(x);
}),
); // => [1, 2, 3]
callbackfnA function to execute for each element in the array.ObjectforEachObjIterate an object using a defined callback function.
The dataLast version returns the original object (instead of not returning
anything (void)) to allow using it in a pipe. The returned object is the
same reference as the input object, and not a shallow copy of it!
Data First
P.forEachObj(object, fn);
P.forEachObj({ a: 1 }, (val, key, obj) => {
console.log(`${key}: ${val}`);
}); // "a: 1"
dataThe object who'se entries would be iterated on.callbackfnA function to execute for each element in the array.voidData Last
P.forEachObj(fn)(object);
P.pipe(
{ a: 1 },
P.forEachObj((val, key) => console.log(`${key}: ${val}`)),
); // "a: 1"
callbackfnA function to execute for each element in the array.ObjectfromEntriesCreates a new object from an array of tuples by pairing up first and second elements as {key: value}. If a tuple is not supplied for any element in the array, the element will be ignored If duplicate keys exist, the tuple with the greatest index in the input array will be preferred.
The strict option supports more sophisticated use-cases like those that would
result when calling the strict toPairs function.
There are several other functions that could be used to build an object from an array:
fromKeys: Builds an object from an array of keys and a mapper for values.indexBy: Builds an object from an array of values and a mapper for keys.pullObject: Builds an object from an array of items with mappers for both keys and values.mapToObj: Builds an object from an array of items and a single mapper for key-value pairs.
Refer to the docs for more details.Data First
P.fromEntries(tuples);
P.fromEntries([
['a', 'b'],
['c', 'd'],
]); // => {a: 'b', c: 'd'}
entriesAn array of key-value pairs.ObjectData Last
P.fromEntries()(tuples);
P.pipe(
[
['a', 'b'],
['c', 'd'],
] as const,
P.fromEntries(),
); // => {a: 'b', c: 'd'}
ObjectfromKeysCreates an object that maps each key in data to the result of mapper for
that key. Duplicate keys are overwritten, guaranteeing that mapper is run
for each item in data.
There are several other functions that could be used to build an object from
an array:
indexBy - Builds an object from an array of values and a mapper for keys.
pullObject - Builds an object from an array of items with mappers for both keys and values.
fromEntries - Builds an object from an array of key-value pairs.
mapToObj - Builds an object from an array of items and a single mapper for key-value pairs.
Refer to the docs for more details.
Data First
P.fromKeys(data, mapper);
P.fromKeys(['cat', 'dog'], P.length()); // { cat: 3, dog: 3 } (typed as Partial<Record<"cat" | "dog", number>>)
P.fromKeys([1, 2], P.add(1)); // { 1: 2, 2: 3 } (typed as Partial<Record<1 | 2, number>>)
dataAn array of keys of the output object. All items in the array
would be keys in the output array.mapperTakes a key and returns the value that would be associated
with that key.ObjectData Last
P.fromKeys(mapper)(data);
P.pipe(['cat', 'dog'], P.fromKeys(P.length())); // { cat: 3, dog: 3 } (typed as Partial<Record<"cat" | "dog", number>>)
P.pipe([1, 2], P.fromKeys(P.add(1))); // { 1: 2, 2: 3 } (typed as Partial<Record<1 | 2, number>>)
mapperTakes a key and returns the value that would be associated
with that key.ObjectfunnelCreates a funnel that controls the timing and execution of callback. Its
main purpose is to manage multiple consecutive (usually fast-paced) calls,
reshaping them according to a defined batching strategy and timing policy.
This is useful when handling uncontrolled call rates, such as DOM events or
network traffic. It can implement strategies like debouncing, throttling,
batching, and more.
An optional reducer function can be provided to allow passing data to the
callback via calls to call (otherwise the signature of call takes no
arguments).
Typing is inferred from callbacks param, and from the rest params that
the optional reducer function accepts. Use explicit types for these
to ensure that everything else is well-typed.
Notice that this function constructs a funnel object, and does not
execute anything when called. The returned object should be used to execute
the funnel via the its call method.
minQuietPeriodMs and any triggerAt.minGapMs and triggerAt: "start" or "both".funnel.reference-batch.test.ts.P.funnel(callback, options);
const debouncer = P.funnel(
() => {
console.log('Callback executed!');
},
{ minQuietPeriodMs: 100 },
);
debouncer.call();
debouncer.call();
const throttle = P.funnel(
() => {
console.log('Callback executed!');
},
{ minGapMs: 100, triggerAt: 'start' },
);
throttle.call();
throttle.call();
callbackThe main function that would be invoked periodically based
on `options`. The function would take the latest result of the `reducer`; if
no calls where made since the last time it was invoked it will not be
invoked. (If a return value is needed, it should be passed via a reference or
via closure to the outer scope of the funnel).optionsAn object that defines when `execute` should be invoked,
relative to the calls of `call`. An empty/missing options object is
equivalent to setting `minQuietPeriodMs` to `0`.ObjectgroupByGroups the elements of a given iterable according to the string values
returned by a provided callback function. The returned object has separate
properties for each group, containing arrays with the elements in the group.
Unlike the built in Object.groupBy this function also allows the callback to
return undefined in order to exclude the item from being added to any
group.
Data First
P.groupBy(data, callbackfn);
P.groupBy([{ a: 'cat' }, { a: 'dog' }] as const, P.prop('a')); // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]}
P.groupBy([0, 1], (x) => (x % 2 === 0 ? 'even' : undefined)); // => {even: [0]}
dataThe items to group.callbackfnA function to execute for each element in the iterable.
It should return a value indicating the group of the current element, or
`undefined` when the item should be excluded from any group.ObjectData Last
P.groupBy(callbackfn)(data);
P.pipe([{ a: 'cat' }, { a: 'dog' }] as const, P.groupBy(P.prop('a'))); // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]}
P.pipe(
[0, 1],
P.groupBy((x) => (x % 2 === 0 ? 'even' : undefined)),
); // => {even: [0]}
callbackfnA function to execute for each element in the iterable.
It should return a value indicating the group of the current element, or
`undefined` when the item should be excluded from any group.ObjecthasAtLeastChecks if the given array has at least the defined number of elements. When
the minimum used is a literal (e.g. 3) the output is refined accordingly so
that those indices are defined when accessing the array even when using
typescript's 'noUncheckedIndexAccess'.
Data First
P.hasAtLeast(data, minimum);
P.hasAtLeast([], 4); // => false
const data: number[] = [1, 2, 3, 4];
P.hasAtLeast(data, 1); // => true
data[0]; // 1, with type `number`
dataThe input array.minimumThe minimum number of elements the array must have.booleanData Last
P.hasAtLeast(minimum)(data);
P.pipe([], P.hasAtLeast(4)); // => false
const data = [[1, 2], [3], [4, 5]];
P.pipe(
data,
P.filter(P.hasAtLeast(2)),
P.map(([, second]) => second),
); // => [2,5], with type `number[]`
minimumThe minimum number of elements the array must have.ObjecthasSubObjectChecks if subObject is a sub-object of object, which means for every
property and value in subObject, there's the same property in object
with an equal value. Equality is checked with isDeepEqual.
Data First
P.hasSubObject(data, subObject);
P.hasSubObject({ a: 1, b: 2, c: 3 }, { a: 1, c: 3 }); //=> true
P.hasSubObject({ a: 1, b: 2, c: 3 }, { b: 4 }); //=> false
P.hasSubObject({ a: 1, b: 2, c: 3 }, {}); //=> true
dataThe object to test.subObjectThe sub-object to test against.booleanData Last
P.hasSubObject(subObject)(data);
P.hasSubObject({ a: 1, c: 3 })({ a: 1, b: 2, c: 3 }); //=> true
P.hasSubObject({ b: 4 })({ a: 1, b: 2, c: 3 }); //=> false
P.hasSubObject({})({ a: 1, b: 2, c: 3 }); //=> true
subObjectThe sub-object to test against.ObjecthumanReadableFileSizeReturns human readable file size.
P.humanReadableFileSize(bytes, base);
P.humanReadableFileSize(1000); // => '1.0 kB'
P.humanReadableFileSize(2097152, 1024); // => '2.0 Mib'
bytesthe file size in bytesbasethe base (1000 or 1024)stringidentityA function that returns the first argument passed to it.
Notice that this is a dataLast impl where the function needs to be invoked to get the "do nothing" function.
See also:
doNothing - A function that doesn't return anything.
constant - A function that ignores the input arguments and returns the same value on every invocation.
P.identity();
P.map([1, 2, 3], P.identity()); // => [1,2,3]
ObjectindexByConverts a list of objects into an object indexing the objects by the given key.
There are several other functions that could be used to build an object from
an array:
fromKeys - Builds an object from an array of keys and a mapper for values.
pullObject - Builds an object from an array of items with mappers for both keys and values.
fromEntries - Builds an object from an array of key-value pairs.
mapToObj - Builds an object from an array of items and a single mapper for key-value pairs.
Refer to the docs for more details.
Data First
P.indexBy(array, fn);
P.indexBy(['one', 'two', 'three'], (x) => x.length); // => {3: 'two', 5: 'three'}
dataThe array.mapperThe indexing function.ObjectData Last
P.indexBy(fn)(array);
P.pipe(
['one', 'two', 'three'],
P.indexBy((x) => x.length),
); // => {3: 'two', 5: 'three'}
mapperThe indexing function.ObjectintersectionReturns a list of elements that exist in both array. The output maintains the same order as the input. The inputs are treated as multi-sets/bags (multiple copies of items are treated as unique items).
Data First
P.intersection(data, other);
P.intersection([1, 2, 3], [2, 3, 5]); // => [2, 3]
P.intersection([1, 1, 2, 2], [1]); // => [1]
dataThe input items.otherThe items to compare against.ArrayData First
P.intersection(other)(data);
P.pipe([1, 2, 3], P.intersection([2, 3, 5])); // => [2, 3]
P.pipe([1, 1, 2, 2], P.intersection([1])); // => [1]
otherThe items to compare against.ObjectintersectionWithReturns a list of intersecting values based on a custom comparator function that compares elements of both arrays.
Data First
P.intersectionWith(array, other, comparator);
P.intersectionWith(
[
{ id: 1, name: 'Ryan' },
{ id: 3, name: 'Emma' },
],
[3, 5],
(a, b) => a.id === b,
); // => [{ id: 3, name: 'Emma' }]
arrayThe source array.otherThe second array.comparatorThe custom comparator.ArrayData Last
P.intersectionWith(other, comparator)(array);
P.intersectionWith(
[3, 5],
(a, b) => a.id === b,
)([
{ id: 1, name: 'Ryan' },
{ id: 3, name: 'Emma' },
]); // => [{ id: 3, name: 'Emma' }]
otherThe second array.comparatorThe custom comparator.ObjectinvertReturns an object whose keys and values are swapped. If the object contains duplicate values, subsequent values will overwrite previous values.
Data First
P.invert(object);
P.invert({ a: 'd', b: 'e', c: 'f' }); // => { d: "a", e: "b", f: "c" }
objectThe object.ObjectData Last
P.invert()(object);
P.pipe({ a: 'd', b: 'e', c: 'f' }, P.invert()); // => { d: "a", e: "b", f: "c" }
ObjectisArrayA function that checks if the passed parameter is an Array and narrows its type accordingly.
P.isArray(data);
P.isArray([5]); //=> true
P.isArray([]); //=> true
P.isArray('somethingElse'); //=> false
dataThe variable to check.booleanisBigIntA function that checks if the passed parameter is a bigint and narrows its type accordingly.
P.isBigInt(data);
P.isBigInt(1n); // => true
P.isBigInt(1); // => false
P.isBigInt('notANumber'); // => false
dataThe variable to check.booleanisBooleanA function that checks if the passed parameter is a boolean and narrows its type accordingly.
P.isBoolean(data);
P.isBoolean(true); //=> true
P.isBoolean(false); //=> true
P.isBoolean('somethingElse'); //=> false
dataThe variable to check.booleanisDateA function that checks if the passed parameter is a Date and narrows its type accordingly.
P.isDate(data);
P.isDate(new Date()); //=> true
P.isDate('somethingElse'); //=> false
dataThe variable to check.booleanisDeepEqualPerforms a deep structural comparison between two values to determine if
they are equivalent. For primitive values this is equivalent to ===, for
arrays the check would be performed on every item recursively, in order, and
for objects all props will be compared recursively.
The built-in Date and RegExp are special-cased and will be compared by their values.
!IMPORTANT: TypedArrays and symbol properties of objects are not supported right now and might result in unexpected behavior.
The result would be narrowed to the second value so that the function can be used as a type guard.
See:
isStrictEqual if you don't need a deep comparison and just want to
check for simple (===, Object.is) equality.isShallowEqual if you need to compare arrays and objects "by-value" but
don't want to recurse into their values.Data First
P.isDeepEqual(data, other);
P.isDeepEqual(1, 1); //=> true
P.isDeepEqual(1, '1'); //=> false
P.isDeepEqual([1, 2, 3], [1, 2, 3]); //=> true
dataThe first value to compare.otherThe second value to compare.booleanData Last
P.isDeepEqual(other)(data);
P.pipe(1, P.isDeepEqual(1)); //=> true
P.pipe(1, P.isDeepEqual('1')); //=> false
P.pipe([1, 2, 3], P.isDeepEqual([1, 2, 3])); //=> true
otherThe second value to compare.ObjectisDefinedA function that checks if the passed parameter is defined (!== undefined)
and narrows its type accordingly.
P.isDefined(data);
P.isDefined('string'); //=> true
P.isDefined(null); //=> true
P.isDefined(undefined); //=> false
dataThe variable to check.booleanisEmptyA function that checks if the passed parameter is empty.
undefined is also considered empty, but only when it's in a union with a
string or string-like type.
This guard doesn't work negated because of typescript limitations! If you
need to check that an array is not empty, use P.hasAtLeast(data, 1)
and not !P.isEmpty(data). For strings and objects there's no way in
typescript to narrow the result to a non-empty type.
P.isEmpty(data);
P.isEmpty(undefined); //=>true
P.isEmpty(''); //=> true
P.isEmpty([]); //=> true
P.isEmpty({}); //=> true
P.isEmpty('test'); //=> false
P.isEmpty([1, 2, 3]); //=> false
P.isEmpty({ length: 0 }); //=> false
dataThe variable to check.booleanisErrorA function that checks if the passed parameter is an Error and narrows its type accordingly.
P.isError(data);
P.isError(new Error('message')); //=> true
P.isError('somethingElse'); //=> false
dataThe variable to check.booleanisFunctionA function that checks if the passed parameter is a Function and narrows its type accordingly.
P.isFunction(data);
P.isFunction(() => {}); //=> true
P.isFunction('somethingElse'); //=> false
dataThe variable to check.booleanisIncludedInChecks if the item is included in the container. This is a wrapper around
Array.prototype.includes and Set.prototype.has and thus relies on the
same equality checks that those functions do (which is reference equality,
e.g. ===). In some cases the input's type is also narrowed to the
container's item types.
Notice that unlike most functions, this function takes a generic item as it's data and an array as it's parameter.
Data First
P.isIncludedIn(data, container);
P.isIncludedIn(2, [1, 2, 3]); // => true
P.isIncludedIn(4, [1, 2, 3]); // => false
const data = 'cat' as 'cat' | 'dog' | 'mouse';
P.isIncludedIn(data, ['cat', 'dog'] as const); // true (typed "cat" | "dog");
dataThe item that is checked.containerThe items that are checked against.booleanData Last
P.isIncludedIn(container)(data);
P.pipe(2, P.isIncludedIn([1, 2, 3])); // => true
P.pipe(4, P.isIncludedIn([1, 2, 3])); // => false
const data = 'cat' as 'cat' | 'dog' | 'mouse';
P.pipe(data, P.isIncludedIn(['cat', 'dog'] as const)); // => true (typed "cat" | "dog");
containerThe items that are checked against.ObjectisNonNullA function that checks if the passed parameter is not null and narrows its type accordingly.
Notice that undefined is not null!
P.isNonNull(data);
P.isNonNull('string'); //=> true
P.isNonNull(null); //=> false
P.isNonNull(undefined); //=> true
dataThe variable to check.booleanisNonNullishA function that checks if the passed parameter is defined AND isn't null
and narrows its type accordingly.
P.isNonNullish(data);
P.isNonNullish('string'); //=> true
P.isNonNullish(null); //=> false
P.isNonNullish(undefined); //=> false
dataThe variable to check.booleanisNotA function that takes a guard function as predicate and returns a guard that negates it.
Data Last
P.isNot(P.isTruthy)(data);
P.isNot(P.isTruthy)(false); //=> true
P.isNot(P.isTruthy)(true); //=> false
predicateThe guard function to negate.ObjectisNullishA function that checks if the passed parameter is either null or
undefined and narrows its type accordingly.
P.isNullish(data);
P.isNullish(undefined); //=> true
P.isNullish(null); //=> true
P.isNullish('somethingElse'); //=> false
dataThe variable to check.booleanisNumberA function that checks if the passed parameter is a number and narrows its type accordingly.
P.isNumber(data);
P.isNumber(1); // => true
P.isNumber(1n); // => false
P.isNumber('notANumber'); // => false
dataThe variable to check.booleanisObjectTypeChecks if the given parameter is of type "object" via typeof, excluding null.
It's important to note that in JavaScript, many entities are considered objects, like Arrays, Classes, RegExps, Maps, Sets, Dates, URLs, Promise, Errors, and more.
Although technically an object too, null is not considered an object by this function, so that its easier to narrow nullables.
For a more specific check that is limited to plain objects (simple struct/shape/record-like objects), consider using isPlainObject instead.
For a simpler check that only removes null from the type prefer isNonNull or isDefined.
Data First
P.isObjectType(data);
// true
P.isObjectType({}); //=> true
P.isObjectType([]); //=> true
P.isObjectType(Promise.resolve('something')); //=> true
P.isObjectType(new Date()); //=> true
P.isObjectType(new Error('error')); //=> true
// false
P.isObjectType('somethingElse'); //=> false
P.isObjectType(null); //=> false
dataThe variable to be checked for being an object type.booleanisPlainObjectChecks if data is a "plain" object. A plain object is defined as an object with string keys and values of any type, including primitives, other objects, functions, classes, etc (aka struct/shape/record/simple). Technically, a plain object is one whose prototype is either Object.prototype or null, ensuring it does not inherit properties or methods from other object types.
This function is narrower in scope than isObjectType, which accepts any entity considered an "object" by JavaScript's typeof.
Note that Maps, Arrays, and Sets are not considered plain objects and would return false.
P.isPlainObject(data);
// true
P.isPlainObject({}); //=> true
P.isPlainObject({ a: 123 }); //=> true
// false
P.isPlainObject([]); //=> false
P.isPlainObject(Promise.resolve('something')); //=> false
P.isPlainObject(new Date()); //=> false
P.isPlainObject(new Error('error')); //=> false
P.isPlainObject('somethingElse'); //=> false
P.isPlainObject(null); //=> false
dataThe variable to check.booleanisPromiseA function that checks if the passed parameter is a Promise and narrows its type accordingly.
P.isPromise(data);
P.isPromise(Promise.resolve(5)); //=> true
P.isPromise(Promise.reject(5)); //=> true
P.isPromise('somethingElse'); //=> false
dataThe variable to check.booleanisShallowEqualPerforms a shallow structural comparison between two values to determine if
they are equivalent. For primitive values this is equivalent to ===, for
arrays a strict equality check would be performed on every item, in
order, and for objects props will be matched and checked for strict
equality; Unlike isDeepEqual where the function also recurses into each
item and value.
!IMPORTANT: Promise, Date, and RegExp, are shallowly equal, even when they
are semantically different (e.g. resolved promises); but isDeepEqual does
compare the latter 2 semantically by-value.
The result would be narrowed to the second value so that the function can be used as a type guard.
See:
isStrictEqual if you don't need a deep comparison and just want to check
for simple (===, Object.is) equality.isDeepEqual for a recursively deep check of arrays and objects.Data First
P.isShallowEqual(data, other);
P.isShallowEqual(1, 1); //=> true
P.isShallowEqual(1, '1'); //=> false
P.isShallowEqual([1, 2, 3], [1, 2, 3]); //=> true
P.isShallowEqual([[1], [2], [3]], [[1], [2], [3]]); //=> false
dataThe first value to compare.otherThe second value to compare.booleanData First
P.isShallowEqual(other)(data);
P.pipe(1, P.isShallowEqual(1)); //=> true
P.pipe(1, P.isShallowEqual('1')); //=> false
P.pipe([1, 2, 3], P.isShallowEqual([1, 2, 3])); //=> true
P.pipe([[1], [2], [3]], P.isShallowEqual([[1], [2], [3]])); //=> false
otherThe second value to compare.ObjectisStrictEqualDetermines whether two values are functionally identical in all contexts. For primitive values (string, number), this is done by-value, and for objects it is done by-reference (i.e., they point to the same object in memory).
Under the hood we use both the === operator
and Object.is. This means that isStrictEqual(NaN, NaN) === true
(whereas NaN !== NaN), and isStrictEqual(-0, 0) === true (whereas
Object.is(-0, 0) === false).
The result would be narrowed to the second value so that the function can be used as a type guard.
See:
isDeepEqual for a semantic comparison that allows comparing arrays and
objects "by-value", and recurses for every item.isShallowEqual if you need to compare arrays and objects "by-value" but
don't want to recurse into their values.Data First
P.isStrictEqual(data, other);
P.isStrictEqual(1, 1); //=> true
P.isStrictEqual(1, '1'); //=> false
P.isStrictEqual([1, 2, 3], [1, 2, 3]); //=> false
dataThe first value to compare.otherThe second value to compare.booleanData Last
P.isStrictEqual(other)(data);
P.pipe(1, P.isStrictEqual(1)); //=> true
P.pipe(1, P.isStrictEqual('1')); //=> false
P.pipe([1, 2, 3], P.isStrictEqual([1, 2, 3])); //=> false
otherThe second value to compare.ObjectisStringA function that checks if the passed parameter is a string and narrows its type accordingly.
P.isString(data);
P.isString('string'); //=> true
P.isString(1); //=> false
dataThe variable to check.booleanisSymbolA function that checks if the passed parameter is a symbol and narrows its type accordingly.
P.isSymbol(data);
P.isSymbol(Symbol('foo')); //=> true
P.isSymbol(1); //=> false
dataThe variable to check.booleanisTruthyA function that checks if the passed parameter is truthy and narrows its type accordingly.
P.isTruthy(data);
P.isTruthy('somethingElse'); //=> true
P.isTruthy(null); //=> false
P.isTruthy(undefined); //=> false
P.isTruthy(false); //=> false
P.isTruthy(0); //=> false
P.isTruthy(''); //=> false
dataThe variable to check.booleanjoinJoins the elements of the array by: casting them to a string and concatenating them one to the other, with the provided glue string in between every two elements.
When called on a tuple and with stricter item types (union of literal values, the result is strictly typed to the tuples shape and it's item types).
Data First
P.join(data, glue);
P.join([1, 2, 3], ','); // => "1,2,3" (typed `string`)
P.join(['a', 'b', 'c'], ''); // => "abc" (typed `string`)
P.join(['hello', 'world'] as const, ' '); // => "hello world" (typed `hello world`)
dataThe array to join.glueThe string to put in between every two elements.ObjectData Last
P.join(glue)(data);
P.pipe([1, 2, 3], P.join(',')); // => "1,2,3" (typed `string`)
P.pipe(['a', 'b', 'c'], P.join('')); // => "abc" (typed `string`)
P.pipe(['hello', 'world'] as const, P.join(' ')); // => "hello world" (typed `hello world`)
glueThe string to put in between every two elements.ObjectkeysReturns a new array containing the keys of the array or object.
Data First
P.keys(source);
P.keys(['x', 'y', 'z']); // => ['0', '1', '2']
P.keys({ a: 'x', b: 'y', 5: 'z' }); // => ['a', 'b', '5']
dataEither an array or an object.ObjectData Last
P.keys()(source);
P.Pipe(['x', 'y', 'z'], keys()); // => ['0', '1', '2']
P.pipe({ a: 'x', b: 'y', 5: 'z' } as const, P.keys()); // => ['a', 'b', '5']
ObjectlastGets the last element of array.
Data First
P.last(array);
P.last([1, 2, 3]); // => 3
P.last([]); // => undefined
dataThe array.ObjectData Last
P.last()(array);
P.pipe(
[1, 2, 4, 8, 16],
P.filter((x) => x > 3),
P.last(),
(x) => x + 1,
); // => 17
ObjectlengthCounts values of the collection or iterable.
Data First
P.length(array);
P.length([1, 2, 3]); // => 3
itemsThe input data.numberData Last
P.length()(array);
P.pipe([1, 2, 3], P.length()); // => 3
ObjectmapCreates a new array populated with the results of calling a provided function
on every element in the calling array. Equivalent to Array.prototype.map.
Data First
P.map(data, callbackfn);
P.map([1, 2, 3], P.multiply(2)); // => [2, 4, 6]
P.map([0, 0], P.add(1)); // => [1, 1]
P.map([0, 0], (value, index) => value + index); // => [0, 1]
dataThe array to map.callbackfnA function to execute for each element in the array. Its
return value is added as a single element in the new array.ObjectData Last
P.map(callbackfn)(data);
P.pipe([1, 2, 3], P.map(P.multiply(2))); // => [2, 4, 6]
P.pipe([0, 0], P.map(P.add(1))); // => [1, 1]
P.pipe(
[0, 0],
P.map((value, index) => value + index),
); // => [0, 1]
callbackfnA function to execute for each element in the array. Its
return value is added as a single element in the new array.ObjectmapKeysMaps keys of object and keeps the same values.
Data First
P.mapKeys(object, fn);
P.mapKeys({ a: 1, b: 2 }, (key, value) => key + value); // => { a1: 1, b2: 2 }
dataThe object to map.keyMapperThe mapping function.ObjectData Last
P.mapKeys(fn)(object);
P.pipe(
{ a: 1, b: 2 },
P.mapKeys((key, value) => key + value),
); // => { a1: 1, b2: 2 }
keyMapperThe mapping function.ObjectmapToObjMap each element of an array into an object using a defined callback function.
There are several other functions that could be used to build an object from
an array:
fromKeys - Builds an object from an array of keys and a mapper for values.
indexBy - Builds an object from an array of values and a mapper for keys.
pullObject - Builds an object from an array of items with mappers for both keys and values.
fromEntries - Builds an object from an array of key-value pairs.
Refer to the docs for more details.
Data First
P.mapToObj(array, fn);
P.mapToObj([1, 2, 3], (x) => [String(x), x * 2]); // => {1: 2, 2: 4, 3: 6}
arrayThe array to map.fnThe mapping function, which should return a tuple of [key, value], similar to Object.fromEntries.ObjectData Last
P.mapToObj(fn)(array);
P.pipe(
[1, 2, 3],
P.mapToObj((x) => [String(x), x * 2]),
); // => {1: 2, 2: 4, 3: 6}
fnThe mapping function, which should return a tuple of [key, value], similar to Object.fromEntries.ObjectmapValuesMaps values of object and keeps the same keys. Symbol keys are not passed
to the mapper and will be removed from the output object.
To also copy the symbol keys to the output use merge:
merge(data, mapValues(data, mapper))).
Data First
P.mapValues(data, mapper);
P.mapValues({ a: 1, b: 2 }, (value, key) => value + key); // => {a: '1a', b: '2b'}
dataThe object to map.valueMapperThe mapping function.ObjectData Last
P.mapValues(mapper)(data);
P.pipe(
{ a: 1, b: 2 },
P.mapValues((value, key) => value + key),
); // => {a: '1a', b: '2b'}
valueMapperThe mapping function.ObjectmapWithFeedbackApplies a function on each element of the array, using the result of the previous application, and returns an array of the successively computed values.
Data First
P.mapWithFeedback(data, callbackfn, initialValue);
P.mapWithFeedback([1, 2, 3, 4, 5], (prev, x) => prev + x, 100); // => [101, 103, 106, 110, 115]
dataThe array to map over.callbackfnThe callback function that receives the previous value,
the current element.initialValueThe initial value to start the computation with.ObjectData Last
P.mapWithFeedback(callbackfn, initialValue)(data);
P.pipe(
[1, 2, 3, 4, 5],
P.mapWithFeedback((prev, x) => prev + x, 100),
); // => [101, 103, 106, 110, 115]
callbackfnThe callback function that receives the previous value,
the current element.initialValueThe initial value to start the computation with.ObjectmeanByReturns the mean of the elements of an array using the provided predicate.
Data Last
P.meanBy(fn)(array);
P.pipe(
[{ a: 5 }, { a: 1 }, { a: 3 }],
P.meanBy((x) => x.a),
); // 3
fnPredicate function.ObjectData First
P.meanBy(array, fn);
P.meanBy([{ a: 5 }, { a: 1 }, { a: 3 }], (x) => x.a); // 3
itemsThe array.fnPredicate function.numbermergeMerges two objects into one by combining their properties, effectively creating a new object that incorporates elements from both. The merge operation prioritizes the second object's properties, allowing them to overwrite those from the first object with the same names.
Equivalent to { ...data, ...source }.
Data First
P.merge(data, source);
P.merge({ x: 1, y: 2 }, { y: 10, z: 2 }); // => { x: 1, y: 10, z: 2 }
dataThe destination object, serving as the basis for the merge.
Properties from this object are included in the new object, but will be
overwritten by properties from the source object with matching keys.sourceThe source object, whose properties will be included in the
new object. If properties in this object share keys with properties in the
destination object, the values from the source object will be used in the
new object.ObjectData Last
P.merge(source)(data);
P.pipe({ x: 1, y: 2 }, P.merge({ y: 10, z: 2 })); // => { x: 1, y: 10, z: 2 }
sourceThe source object, whose properties will be included in the
new object. If properties in this object share keys with properties in the
destination object, the values from the source object will be used in the
new object.ObjectmergeAllMerges a list of objects into a single object.
P.mergeAll(objects);
P.mergeAll([{ a: 1, b: 1 }, { b: 2, c: 3 }, { d: 10 }]); // => { a: 1, b: 2, c: 3, d: 10 }
arrayThe array of objects.ObjectmergeDeepMerges the source object into the destination object. The merge is similar to performing { ...destination, ... source } (where disjoint values from each object would be copied as-is, and for any overlapping props the value from source would be used); But for each prop (p), if both destination and source have a plain-object as a value, the value would be taken as the result of recursively deepMerging them (result.p === deepMerge(destination.p, source.p)).
Data First
P.mergeDeep(destination, source);
P.mergeDeep({ foo: 'bar', x: 1 }, { foo: 'baz', y: 2 }); // => { foo: 'baz', x: 1, y: 2 }
destinationThe object to merge into. In general, this object would have it's values overridden.sourceThe object to merge from. In general, shared keys would be taken from this object.ObjectData Last
P.mergeDeep(source)(destination);
P.pipe({ foo: 'bar', x: 1 }, P.mergeDeep({ foo: 'baz', y: 2 })); // => { foo: 'baz', x: 1, y: 2 }
sourceThe object to merge from. In general, shared keys would be taken from this object.ObjectmultiplyMultiplies two numbers.
Data First
P.multiply(value, multiplicand);
P.multiply(3, 4); // => 12
P.reduce([1, 2, 3, 4], P.multiply, 1); // => 24
valueThe number.multiplicandThe number to multiply the value by.bigintData Last
P.multiply(multiplicand)(value);
P.multiply(4)(3); // => 12
P.map([1, 2, 3, 4], P.multiply(2)); // => [2, 4, 6, 8]
multiplicandThe number to multiply the value by.ObjectnthByRetrieves the element that would be at the given index if the array were sorted according to specified rules. This function uses the QuickSelect algorithm running at an average complexity of O(n). Semantically it is equivalent to sortBy(data, ...rules).at(index) which would run at O(nlogn).
See also firstBy which provides an even more efficient algorithm and a stricter return type, but only for index === 0. See takeFirstBy to get all the elements up to and including index.
Data First
P.nthBy(data, index, ...rules);
P.nthBy([2, 1, 4, 5, 3], 2, identity()); // => 3
dataThe input array.indexThe zero-based index for selecting the element in the sorted order. Negative indices count backwards from the end.rulesA variadic array of order rules defining the sorting criteria. Each order rule is a projection function that extracts a comparable value from the data. Sorting is based on these extracted values using the native `<` and `>` operators. Earlier rules take precedence over later ones. Use the syntax `[projection, "desc"]` for descending order.ObjectData Last
P.nthBy(index, ...rules)(data);
P.pipe([2, 1, 4, 5, 3], P.nthBy(2, identity())); // => 3
indexThe zero-based index for selecting the element in the sorted order. Negative indices count backwards from the end.rulesA variadic array of order rules defining the sorting criteria. Each order rule is a projection function that extracts a comparable value from the data. Sorting is based on these extracted values using the native `<` and `>` operators. Earlier rules take precedence over later ones. Use the syntax `[projection, "desc"]` for descending order.ObjectobjOfCreates an object containing a single key:value pair.
P.objOf(value, key);
P.objOf(10, 'a'); // => { a: 10 }
valueThe object value.keyThe property name.ObjectP.objOf(key)(value);
P.pipe(10, P.objOf('a')); // => { a: 10 }
keyThe property name.ObjectomitReturns a partial copy of an object omitting the keys specified.
Data Last
P.omit(names)(obj);
P.pipe({ a: 1, b: 2, c: 3, d: 4 }, P.omit(['a', 'd'])); // => { b: 2, c: 3 }
propNamesThe property names.ObjectData First
P.omit(obj, names);
P.omit({ a: 1, b: 2, c: 3, d: 4 }, ['a', 'd']); // => { b: 2, c: 3 }
dataThe object.propNamesThe property names.ObjectomitByCreates a shallow copy of the data, and then removes any keys that the predicate rejects. Symbol keys are not passed to the predicate and would be passed through to the output as-is.
See pickBy for a complementary function which starts with an empty object
and adds the entries that the predicate accepts. Because it is additive,
symbol keys will not be passed through to the output object.
Data First
P.omitBy(data, predicate);
P.omitBy({ a: 1, b: 2, A: 3, B: 4 }, (val, key) => key.toUpperCase() === key); // => {a: 1, b: 2}
dataThe target object.predicateA function that takes the value, key, and the data itself
and returns `true` if the entry shouldn't be part of the output object, or
`false` to keep it. If the function is a type-guard on the value the output
type would be narrowed accordingly.ObjectData Last
P.omitBy(fn)(object);
P.omitBy((val, key) => key.toUpperCase() === key)({ a: 1, b: 2, A: 3, B: 4 }); // => {a: 1, b: 2}
predicateThe predicate.ObjectonceCreates a function that is restricted to invoking func once. Repeat calls to the function return the value of the first invocation.
P.once(fn);
const initialize = P.once(createApplication);
initialize();
initialize();
// => `createApplication` is invoked once
fnThe function to wrap.ObjectonlyReturns the first and only element of array, or undefined otherwise.
Data First
P.only(array);
P.only([]); // => undefined
P.only([1]); // => 1
P.only([1, 2]); // => undefined
arrayThe target array.ObjectData Last
P.only()(array);
P.pipe([], P.only()); // => undefined
P.pipe([1], P.only()); // => 1
P.pipe([1, 2], P.only()); // => undefined
ObjectpartitionSplits a collection into two groups, the first of which contains elements the
predicate type guard passes, and the second one containing the rest.
Data First
P.partition(data, predicate);
P.partition(['one', 'two', 'forty two'], (x) => x.length === 3); // => [['one', 'two'], ['forty two']]
dataThe items to split.predicateA function to execute for each element in the array. It
should return `true` to add the element to the first partition, and and
`false` to add the element to the other partition. A type-predicate can also
be used to narrow the result.ObjectData Last
P.partition(predicate)(data);
P.pipe(
['one', 'two', 'forty two'],
P.partition((x) => x.length === 3),
); // => [['one', 'two'], ['forty two']]
predicateA function to execute for each element in the array. It
should return `true` to add the element to the first partition, and and
`false` to add the element to the other partition. A type-predicate can also
be used to narrow the result.ObjectpathOrGets the value at path of object. If the resolved value is null or undefined, the defaultValue is returned in its place.
Data First
P.pathOr(object, array, defaultValue);
P.pathOr({ x: 10 }, ['y'], 2); // 2
P.pathOr({ y: 10 }, ['y'], 2); // 10
objectThe target object.pathThe path of the property to get.defaultValueThe default value.ObjectData Last
P.pathOr(array, defaultValue)(object);
P.pipe({ x: 10 }, P.pathOr(['y'], 2)); // 2
P.pipe({ y: 10 }, P.pathOr(['y'], 2)); // 10
pathThe path of the property to get.defaultValueThe default value.ObjectpickCreates an object composed of the picked object properties.
Data Last
P.pick([prop1, prop2])(object);
P.pipe({ a: 1, b: 2, c: 3, d: 4 }, P.pick(['a', 'd'])); // => { a: 1, d: 4 }
namesThe properties names.ObjectData First
P.pick(object, [prop1, prop2]);
P.pick({ a: 1, b: 2, c: 3, d: 4 }, ['a', 'd']); // => { a: 1, d: 4 }
objectThe target object.namesThe properties names.ObjectpickByIterates over the entries of data and reconstructs the object using only
entries that predicate accepts. Symbol keys are not passed to the predicate
and would be filtered out from the output object.
See omitBy for a complementary function which starts with a shallow copy of
the input object and removes the entries that the predicate rejects. Because
it is subtractive symbol keys would be copied over to the output object.
See also entries, filter, and fromEntries which could be used to build
your own version of pickBy if you need more control (though the resulting
type might be less precise).
Data First
P.pickBy(data, predicate);
P.pickBy({ a: 1, b: 2, A: 3, B: 4 }, (val, key) => key.toUpperCase() === key); // => {A: 3, B: 4}
dataThe target object.predicateA function that takes the value, key, and the data itself
and returns true if the entry should be part of the output object, or `false`
to remove it. If the function is a type-guard on the value the output type
would be narrowed accordingly.ObjectData Last
P.pickBy(predicate)(data);
P.pipe(
{ a: 1, b: 2, A: 3, B: 4 },
pickBy((val, key) => key.toUpperCase() === key),
); // => {A: 3, B: 4}
predicateA function that takes the value, key, and the data itself
and returns true if the entry should be part of the output object, or `false`
to remove it. If the function is a type-guard on the value the output type
would be narrowed accordingly.ObjectpipePerform left-to-right function composition.
Data First
P.pipe(data, op1, op2, op3);
P.pipe(
[1, 2, 3, 4],
P.map((x) => x * 2),
(arr) => [arr[0] + arr[1], arr[2] + arr[3]],
); // => [6, 14]
valueThe initial value.op1ObjectpipedA dataLast version of pipe that could be used to provide more complex
computations to functions that accept a function as a param (like map,
filter, groupBy, etc.).
The first function must be always annotated. Other functions are automatically inferred.
P.piped(...ops)(data);
P.filter(
[{ a: 1 }, { a: 2 }, { a: 3 }],
P.piped(P.prop('a'), (x) => x % 2 === 0),
); // => [{ a: 2 }]
op1ObjectproductCompute the product of the numbers in the array, or return 1 for an empty array.
Works for both number and bigint arrays, but not arrays that contain both
types.
IMPORTANT: The result for empty arrays would be 1 (number) regardless of
the type of the array; to avoid adding this to the return type for cases
where the array is known to be non-empty you can use hasAtLeast or
isEmpty to guard against this case.
Data First
P.product(data);
P.product([1, 2, 3]); // => 6
P.product([1n, 2n, 3n]); // => 6n
P.product([]); // => 1
dataThe array of numbers.ObjectData Last
P.product()(data);
P.pipe([1, 2, 3], P.product()); // => 6
P.pipe([1n, 2n, 3n], R.product()); // => 6n
P.pipe([], P.product()); // => 1
ObjectpropGets the value of the given property.
Data First
P.prop(data, key);
P.prop({ foo: 'bar' }, 'foo'); // => 'bar'
dataThe object to extract the prop from.keyThe key of the property to extract.ObjectData Last
P.prop(key)(data);
P.pipe({ foo: 'bar' }, P.prop('foo')); // => 'bar'
keyThe key of the property to extract.ObjectpullObjectCreates an object that maps the result of valueExtractor with a key
resulting from running keyExtractor on each item in data. Duplicate keys
are overwritten, guaranteeing that the extractor functions are run on each
item in data.
There are several other functions that could be used to build an object from
an array:
fromKeys - Builds an object from an array of keys and a mapper for values.
indexBy - Builds an object from an array of values and a mapper for keys.
fromEntries - Builds an object from an array of key-value pairs.
mapToObj - Builds an object from an array of items and a single mapper for key-value pairs.
Refer to the docs for more details.
Data First
P.pullObject(data, keyExtractor, valueExtractor);
P.pullObject(
[
{ name: 'john', email: 'john@bebedag.com' },
{ name: 'jane', email: 'jane@bebedag.com' },
],
P.prop('name'),
P.prop('email'),
); // => { john: "john@bebedag.com", jane: "jane@bebedag.com" }
dataThe items used to pull/extract the keys and values from.keyExtractorComputes the key for item.valueExtractorComputes the value for the item.ObjectData Last
P.pullObject(keyExtractor, valueExtractor)(data);
P.pipe(
[
{ name: 'john', email: 'john@bebedag.com' },
{ name: 'jane', email: 'jane@bebedag.com' },
],
P.pullObject(P.prop('email'), P.prop('name')),
); // => { john: "john@bebedag.com", jane: "jane@bebedag.com" }
keyExtractorComputes the key for item.valueExtractorComputes the value for the item.ObjectrandomIntegerGenerate a random integer between from and to (inclusive).
Data First
P.randomInt(from, to);
P.randomInt(1, 10); // => 5
P.randomInt(1.5, 2.6); // => 2
fromThe minimum value.toThe maximum value.ObjectrandomStringRandom a non-cryptographic random string from characters a-zA-Z0-9.
Data First
P.randomString(length);
P.randomString(5); // => aB92J
lengthThe length of the random string.stringData Last
P.randomString()(length);
P.pipe(5, P.randomString()); // => aB92J
ObjectrangeReturns a list of numbers from start (inclusive) to end (exclusive).
Data First
range(start, end);
P.range(1, 5); // => [1, 2, 3, 4]
startThe start number.endThe end number.ArrayData First
range(end)(start);
P.range(5)(1); // => [1, 2, 3, 4]
endThe end number.ObjectrankByCalculates the rank of an item in an array based on rules. The rank is the position where the item would appear in the sorted array. This function provides an efficient way to determine the rank in O(n) time, compared to O(nlogn) for the equivalent sortedIndex(sortBy(data, ...rules), item).
Data First
P.rankBy(data, item, ...rules);
const DATA = [{ a: 5 }, { a: 1 }, { a: 3 }] as const;
P.rankBy(DATA, 0, P.prop('a')); // => 0
P.rankBy(DATA, 1, P.prop('a')); // => 1
P.rankBy(DATA, 2, P.prop('a')); // => 1
P.rankBy(DATA, 3, P.prop('a')); // => 2
dataThe input array.itemThe item whose rank is to be determined.rulesA variadic array of order rules defining the sorting criteria. Each order rule is a projection function that extracts a comparable value from the data. Sorting is based on these extracted values using the native `<` and `>` operators. Earlier rules take precedence over later ones. Use the syntax `[projection, "desc"]` for descending order.numberData Last
P.rankBy(item, ...rules)(data);
const DATA = [{ a: 5 }, { a: 1 }, { a: 3 }] as const;
P.pipe(DATA, P.rankBy(0, P.prop('a'))); // => 0
P.pipe(DATA, P.rankBy(1, P.prop('a'))); // => 1
P.pipe(DATA, P.rankBy(2, P.prop('a'))); // => 1
P.pipe(DATA, P.rankBy(3, P.prop('a'))); // => 2
itemThe item whose rank is to be determined.rulesA variadic array of order rules defining the sorting criteria. Each order rule is a projection function that extracts a comparable value from the data. Sorting is based on these extracted values using the native `<` and `>` operators. Earlier rules take precedence over later ones. Use the syntax `[projection, "desc"]` for descending order.ObjectreduceExecutes a user-supplied "reducer" callback function on each element of the
array, in order, passing in the return value from the calculation on the
preceding element. The final result of running the reducer across all
elements of the array is a single value. Equivalent to
Array.prototype.reduce.
Data First
P.reduce(data, callbackfn, initialValue);
P.reduce([1, 2, 3, 4, 5], (acc, x) => acc + x, 100); // => 115
dataThe items to reduce.callbackfnA function to execute for each element in the array. Its
return value becomes the value of the accumulator parameter on the next
invocation of callbackFn. For the last invocation, the return value becomes
the return value of reduce().initialValueA value to which accumulator is initialized the first
time the callback is called. CallbackFn starts executing with the first value
in the array as currentValue.ObjectData Last
P.reduce(fn, initialValue)(array);
P.pipe(
[1, 2, 3, 4, 5],
P.reduce((acc, x) => acc + x, 100),
); // => 115
callbackfnA function to execute for each element in the array. Its
return value becomes the value of the accumulator parameter on the next
invocation of callbackFn. For the last invocation, the return value becomes
the return value of reduce().initialValueA value to which accumulator is initialized the first
time the callback is called. CallbackFn starts executing with the first value
in the array as currentValue.ObjectreverseReverses array.
Data First
P.reverse(arr);
P.reverse([1, 2, 3]); // [3, 2, 1]
arrayThe array.ObjectData Last
P.reverse()(array);
P.reverse()([1, 2, 3]); // [3, 2, 1]
ObjectroundRounds a given number to a specific precision.
If you'd like to round to an integer (i.e. use this function with constant precision === 0),
use Math.round instead, as it won't incur the additional library overhead.
Data First
P.round(value, precision);
P.round(123.9876, 3); // => 123.988
P.round(483.22243, 1); // => 483.2
P.round(8541, -1); // => 8540
P.round(456789, -3); // => 457000
valueThe number to round.precisionThe precision to round to. Must be an integer between -15 and 15.numberData Last
P.round(precision)(value);
P.round(3)(123.9876); // => 123.988
P.round(1)(483.22243); // => 483.2
P.round(-1)(8541); // => 8540
P.round(-3)(456789); // => 457000
precisionThe precision to round to. Must be an integer between -15 and 15.ObjectsampleReturns a random subset of size sampleSize from array.
Maintains and infers most of the typing information that could be passed along to the output. This means that when using tuples, the output will be a tuple too, and when using literals, those literals would be preserved.
The items in the result are kept in the same order as they are in the input. If you need to get a shuffled response you can pipe the shuffle function after this one.
Data First
P.sample(array, sampleSize);
P.sample(['hello', 'world'], 1); // => ["hello"] // typed string[]
P.sample(['hello', 'world'] as const, 1); // => ["world"] // typed ["hello" | "world"]
dataThe array.sampleSizeThe number of elements to take.ObjectData Last
P.sample(sampleSize)(array);
P.sample(1)(['hello', 'world']); // => ["hello"] // typed string[]
P.sample(1)(['hello', 'world'] as const); // => ["world"] // typed ["hello" | "world"]
sampleSizeThe number of elements to take.ObjectsetSets the value at prop of object.
To add a new property to an object, or to override its type, use addProp
instead, and to set a property within a nested object use setPath.
Data First
P.set(obj, prop, value);
P.set({ a: 1 }, 'a', 2); // => { a: 2 }
objThe target method.propThe property name.valueThe value to set.ObjectData Last
P.set(prop, value)(obj);
P.pipe({ a: 1 }, P.set('a', 2)); // => { a: 2 }
propThe property name.valueThe value to set.ObjectsetPathSets the value at path of object.
For simple cases where the path is only one level deep, prefer set instead.
Data First
P.setPath(obj, path, value);
P.setPath({ a: { b: 1 } }, ['a', 'b'], 2); // => { a: { b: 2 } }
dataThe target method.pathThe array of properties.valueThe value to set.ObjectData Last
P.setPath(path, value)(obj);
P.pipe({ a: { b: 1 } }, P.setPath(['a', 'b'], 2)); // { a: { b: 2 } }
pathThe array of properties.valueThe value to set.ObjectshuffleShuffles the input array, returning a new array with the same elements in a random order.
Data First
P.shuffle(array);
P.shuffle([4, 2, 7, 5]); // => [7, 5, 4, 2]
itemsThe array to shuffle.ObjectData Last
P.shuffle()(array);
P.pipe([4, 2, 7, 5], P.shuffle()); // => [7, 5, 4, 2]
ObjectsleepDelay execution for a given number of milliseconds.
P.sleep(timeout);
P.sleep(1000); // => Promise<void>
timeoutthe number of milliseconds to waitObjectsliceStringExtracts a section of this string and returns it as a new string, without
modifying the original string. Equivalent to String.prototype.slice.
Data Last
P.sliceString(data, indexStart, indexEnd);
P.sliceString('abcdefghijkl', 1); // => `bcdefghijkl`
P.sliceString('abcdefghijkl', 4, 7); // => `efg`
dataThe string to extract from.indexStartThe index of the first character to include in the
returned substring.indexEndThe index of the first character to exclude from the
returned substring.stringData Last
P.sliceString(indexStart, indexEnd)(string);
P.sliceString(1)('abcdefghijkl'); // => `bcdefghijkl`
P.sliceString(4, 7)('abcdefghijkl'); // => `efg`
indexStartThe index of the first character to include in the
returned substring.indexEndThe index of the first character to exclude from the
returned substring, or `undefined` for the rest of the string.ObjectslugifyTurn any string into a URL/DOM safe string.
P.slugify(str);
P.slugify('FooBar'); // => 'foobar'
P.slugify('This!-is*&%#@^up!'); // => 'this-is-up'
strthe string to slugifystringsortSorts an array. The comparator function should accept two values at a time
and return a negative number if the first value is smaller, a positive number
if it's larger, and zero if they are equal. Sorting is based on a native
sort function.
Data First
P.sort(items, cmp);
P.sort([4, 2, 7, 5], (a, b) => a - b); // => [2, 4, 5, 7]
itemsThe array to sort.cmpThe comparator function.ObjectData Last
P.sort(cmp)(items);
P.pipe(
[4, 2, 7, 5],
P.sort((a, b) => a - b),
); // => [2, 4, 5, 7]
cmpThe comparator function.ObjectsortBySorts data using the provided ordering rules. The sort is done via the
native Array.prototype.sort but is performed on a shallow copy of the array
to avoid mutating the original data.
There are several other functions that take order rules and bypass the
need to sort the array first (in O(nlogn) time):
firstBy === first(sortBy(data, ...rules)), O(n).
takeFirstBy === take(sortBy(data, ...rules), k), O(nlogk).
dropFirstBy === drop(sortBy(data, ...rules), k), O(nlogk).
nthBy === sortBy(data, ...rules).at(k), O(n).
rankBy === sortedIndex(sortBy(data, ...rules), item), O(n).
Refer to the docs for more details.
Data Last
P.sortBy(...rules)(data);
P.pipe([{ a: 1 }, { a: 3 }, { a: 7 }, { a: 2 }], P.sortBy(P.prop('a'))); // => [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 7 }]
sortRulesA variadic array of order rules defining the sorting
criteria. Each order rule is a projection function that extracts a comparable
value from the data. Sorting is based on these extracted values using the
native `<` and `>` operators. Earlier rules take precedence over later ones.
Use the syntax `[projection, "desc"]` for descending order.ObjectData First
P.sortBy(data, ...rules);
P.sortBy([{ a: 1 }, { a: 3 }, { a: 7 }, { a: 2 }], prop('a')); // => [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 7 }]
P.sortBy(
[
{ color: 'red', weight: 2 },
{ color: 'blue', weight: 3 },
{ color: 'green', weight: 1 },
{ color: 'purple', weight: 1 },
],
[prop('weight'), 'asc'],
prop('color'),
); // => [
// {color: 'green', weight: 1},
// {color: 'purple', weight: 1},
// {color: 'red', weight: 2},
// {color: 'blue', weight: 3},
// ]
arrayThe input array.sortRulesA variadic array of order rules defining the sorting
criteria. Each order rule is a projection function that extracts a comparable
value from the data. Sorting is based on these extracted values using the
native `<` and `>` operators. Earlier rules take precedence over later ones.
Use the syntax `[projection, "desc"]` for descending order.ObjectsortedIndexFind the insertion position (index) of an item in an array with items sorted
in ascending order; so that splice(sortedIndex, 0, item) would result in
maintaining the array's sort-ness. The array can contain duplicates.
If the item already exists in the array the index would be of the first
occurrence of the item.
Runs in O(logN) time.
Data First
P.sortedIndex(data, item);
P.sortedIndex(['a', 'a', 'b', 'c', 'c'], 'c'); // => 3
dataThe (ascending) sorted array.itemThe item to insert.numberData Last
P.sortedIndex(item)(data);
P.pipe(['a', 'a', 'b', 'c', 'c'], P.sortedIndex('c')); // => 3
itemThe item to insert.ObjectsortedIndexByFind the insertion position (index) of an item in an array with items sorted
in ascending order using a value function; so that
splice(sortedIndex, 0, item) would result in maintaining the arrays sort-
ness. The array can contain duplicates.
If the item already exists in the array the index would be of the first
occurrence of the item.
Runs in O(logN) time.
See also:
findIndex - scans a possibly unsorted array in-order (linear search).
sortedIndex - like this function, but doesn't take a callbackfn.
sortedLastIndexBy - like this function, but finds the last suitable index.
sortedLastIndex - like sortedIndex, but finds the last suitable index.
rankBy - scans a possibly unsorted array in-order, returning the index based on a sorting criteria.
Data First
P.sortedIndexBy(data, item, valueFunction);
P.sortedIndexBy([{ age: 20 }, { age: 22 }], { age: 21 }, prop('age')); // => 1
dataThe (ascending) sorted array.itemThe item to insert.valueFunctionAll comparisons would be performed on the result of
calling this function on each compared item. Preferably this function should
return a `number` or `string`. This function should be the same as the one
provided to sortBy to sort the array. The function is called exactly once on
each items that is compared against in the array, and once at the beginning
on `item`. When called on `item` the `index` argument is `undefined`.numbersortedIndexWithPerforms a binary search for the index of the item at which the predicate
stops returning true. This function assumes that the array is "sorted" in
regards to the predicate, meaning that running the predicate as a mapper on
it would result in an array [...true[], ...false[]].
This stricter requirement from the predicate provides us 2 benefits over
findIndex which does a similar thing:
data.length if the
predicate returns true for all items).This function is the basis for all other sortedIndex functions which search
for a specific item in a sorted array, and it could be used to perform
similar efficient searches.
sortedIndex - scans a sorted array with a binary search, find the first suitable index.
sortedIndexBy - like sortedIndex, but assumes sorting is based on a callbackfn.
sortedLastIndex - scans a sorted array with a binary search, finding the last suitable index.
sortedLastIndexBy - like sortedLastIndex, but assumes sorting is based on a callbackfn.
See also:
findIndex - scans a possibly unsorted array in-order (linear search).
rankBy - scans a possibly unsorted array in-order, returning the index based on a sorting criteria.
Data First
P.sortedIndexWith(data, predicate);
P.sortedIndexWith(['a', 'ab', 'abc'], (item) => item.length < 2); // => 1
dataArray, "sorted" by `predicate`.predicateA predicate which also defines the array's order.numberData Last
P.sortedIndexWith(predicate)(data);
P.pipe(
['a', 'ab', 'abc'],
P.sortedIndexWith((item) => item.length < 2),
); // => 1
predicateA predicate which also defines the array's order.ObjectsortedLastIndexFind the insertion position (index) of an item in an array with items sorted
in ascending order; so that splice(sortedIndex, 0, item) would result in
maintaining the array's sort-ness. The array can contain duplicates.
If the item already exists in the array the index would be of the last
occurrence of the item.
Runs in O(logN) time.
Data First
P.sortedLastIndex(data, item);
P.sortedLastIndex(['a', 'a', 'b', 'c', 'c'], 'c'); // => 5
dataThe (ascending) sorted array.itemThe item to insert.numberData Last
P.sortedLastIndex(item)(data);
P.pipe(['a', 'a', 'b', 'c', 'c'], sortedLastIndex('c')); // => 5
itemThe item to insert.ObjectsortedLastIndexByFind the insertion position (index) of an item in an array with items sorted
in ascending order using a value function; so that
splice(sortedIndex, 0, item) would result in maintaining the arrays sort-
ness. The array can contain duplicates.
If the item already exists in the array the index would be of the last
occurrence of the item.
Runs in O(logN) time.
See also:
findIndex - scans a possibly unsorted array in-order (linear search).
sortedLastIndex - a simplified version of this function, without a callbackfn.
sortedIndexBy - like this function, but returns the first suitable index.
sortedIndex - like sortedLastIndex but without a callbackfn.
rankBy - scans a possibly unsorted array in-order, returning the index based on a sorting criteria.
Data First
P.sortedLastIndexBy(data, item, valueFunction);
P.sortedLastIndexBy([{ age: 20 }, { age: 22 }], { age: 21 }, prop('age')); // => 1
dataThe (ascending) sorted array.itemThe item to insert.valueFunctionAll comparisons would be performed on the result of
calling this function on each compared item. Preferably this function should
return a `number` or `string`. This function should be the same as the one
provided to sortBy to sort the array. The function is called exactly once on
each items that is compared against in the array, and once at the beginning
on `item`. When called on `item` the `index` argument is `undefined`.numberData Last
P.sortedLastIndexBy(item, valueFunction)(data);
P.pipe([{ age: 20 }, { age: 22 }], sortedLastIndexBy({ age: 21 }, prop('age'))); // => 1
itemThe item to insert.valueFunctionAll comparisons would be performed on the result of
calling this function on each compared item. Preferably this function should
return a `number` or `string`. This function should be the same as the one
provided to sortBy to sort the array. The function is called exactly once on
each items that is compared against in the array, and once at the beginning
on `item`. When called on `item` the `index` argument is `undefined`.ObjectspliceRemoves elements from an array and, inserts new elements in their place.
Data First
P.splice(items, start, deleteCount, replacement);
P.splice([1, 2, 3, 4, 5, 6, 7, 8], 2, 3, []); //=> [1,2,6,7,8]
P.splice([1, 2, 3, 4, 5, 6, 7, 8], 2, 3, [9, 10]); //=> [1,2,9,10,6,7,8]
itemsThe array to splice.startThe index from which to start removing elements.deleteCountThe number of elements to remove.replacementThe elements to insert into the array in place of the deleted elements.ArrayData Last
P.splice(start, deleteCount, replacement)(items);
P.pipe([1, 2, 3, 4, 5, 6, 7, 8], P.splice(2, 3, [])); // => [1,2,6,7,8]
P.pipe([1, 2, 3, 4, 5, 6, 7, 8], P.splice(2, 3, [9, 10])); // => [1,2,9,10,6,7,8]
startThe index from which to start removing elements.deleteCountThe number of elements to remove.replacementThe elements to insert into the array in place of the deleted elements.ObjectsplitTakes a pattern and divides this string into an ordered list of substrings by
searching for the pattern, puts these substrings into an array, and returns
the array. This function mirrors the built-in String.prototype.split
method.
Data First
R.split(data, separator, limit);
R.split('a,b,c', ','); //=> ["a", "b", "c"]
R.split('a,b,c', ',', 2); //=> ["a", "b"]
R.split('a1b2c3d', /\d/u); //=> ["a", "b", "c", "d"]
dataThe string to split.separatorThe pattern describing where each split should occur. Can
be a string, or a regular expression.limitA non-negative integer specifying a limit on the number of
substrings to be included in the array. If provided, splits the string at
each occurrence of the specified separator, but stops when limit entries have
been placed in the array. Any leftover text is not included in the array at
all. The array may contain fewer entries than limit if the end of the string
is reached before the limit is reached. If limit is 0, [] is returned.ArrayData Last
R.split(separator, limit)(data);
R.pipe('a,b,c', R.split(',')); //=> ["a", "b", "c"]
R.pipe('a,b,c', R.split(',', 2)); //=> ["a", "b"]
R.pipe('a1b2c3d', R.split(/\d/u)); //=> ["a", "b", "c", "d"]
separatorThe pattern describing where each split should occur. Can
be a string, or a regular expression.limitA non-negative integer specifying a limit on the number of
substrings to be included in the array. If provided, splits the string at
each occurrence of the specified separator, but stops when limit entries have
been placed in the array. Any leftover text is not included in the array at
all. The array may contain fewer entries than limit if the end of the string
is reached before the limit is reached. If limit is 0, [] is returned.ObjectsplitAtSplits a given array at a given index.
Data First
P.splitAt(array, index);
P.splitAt([1, 2, 3], 1); // => [[1], [2, 3]]
P.splitAt([1, 2, 3, 4, 5], -1); // => [[1, 2, 3, 4], [5]]
arrayThe array to split.indexThe index to split at.ObjectData Last
P.splitAt(index)(array);
P.splitAt(1)([1, 2, 3]); // => [[1], [2, 3]]
P.splitAt(-1)([1, 2, 3, 4, 5]); // => [[1, 2, 3, 4], [5]]
indexThe index to split at.ObjectsplitWhenSplits a given array at the first index where the given predicate returns true.
Data First
P.splitWhen(array, fn);
P.splitWhen([1, 2, 3], (x) => x === 2); // => [[1], [2, 3]]
dataThe array to split.predicateThe predicate.ObjectData Last
P.splitWhen(fn)(array);
P.splitWhen((x) => x === 2)([1, 2, 3]); // => [[1], [2, 3]]
predicateThe predicate.ObjectstringToPathConverts a path string to an array of string keys (including array index access keys).
! IMPORTANT: Attempting to pass a simple string type will result in the
result being inferred as never. This is intentional to help with type-
safety as this function is primarily intended to help with other "object path
access" functions like pathOr or setPath.
Data First
P.stringToPathArray(path);
P.stringToPathArray('a.b[0].c'); // => ['a', 'b', '0', 'c']
pathA string path.ObjectsubtractSubtracts two numbers.
Data First
P.subtract(value, subtrahend);
P.subtract(10, 5); // => 5
P.subtract(10, -5); // => 15
P.reduce([1, 2, 3, 4], P.subtract, 20); // => 10
valueThe number.subtrahendThe number to subtract from the value.bigintData Last
P.subtract(subtrahend)(value);
P.subtract(5)(10); // => 5
P.subtract(-5)(10); // => 15
P.map([1, 2, 3, 4], P.subtract(1)); // => [0, 1, 2, 3]
subtrahendThe number to subtract from the value.ObjectsumSums the numbers in the array, or return 0 for an empty array.
Works for both number and bigint arrays, but not arrays that contain both
types.
IMPORTANT: The result for empty arrays would be 0 (number) regardless of
the type of the array; to avoid adding this to the return type for cases
where the array is known to be non-empty you can use hasAtLeast or
isEmpty to guard against this case.
Data First
P.sum(data);
P.sum([1, 2, 3]); // => 6
P.sum([1n, 2n, 3n]); // => 6n
P.sum([]); // => 0
dataThe array of numbers.ObjectData Last
P.sum()(data);
P.pipe([1, 2, 3], P.sum()); // => 6
P.pipe([1n, 2n, 3n], R.sum()); // => 6n
P.pipe([], P.sum()); // => 0
ObjectsumByReturns the sum of the elements of an array using the provided mapper.
Works for both number and bigint mappers, but not mappers that return both
types.
IMPORTANT: The result for empty arrays would be 0 (number) regardless of
the type of the mapper; to avoid adding this to the return type for cases
where the array is known to be non-empty you can use hasAtLeast or
isEmpty to guard against this case.
Data Last
P.sumBy(fn)(array);
P.pipe(
[{ a: 5 }, { a: 1 }, { a: 3 }],
P.sumBy((x) => x.a),
); // 9
callbackfnPredicate function.ObjectData First
P.sumBy(array, fn);
P.sumBy([{ a: 5 }, { a: 1 }, { a: 3 }], (x) => x.a); // 9
dataThe array.callbackfnPredicate function.ObjectswapIndicesSwaps the positions of two elements in an array or string at the provided indices.
Negative indices are supported and would be treated as an offset from the end of the array. The resulting type thought would be less strict than when using positive indices.
If either index is out of bounds the result would be a shallow copy of the input, as-is.
Data First
swapIndices(data, index1, index2);
swapIndices(['a', 'b', 'c'], 0, 1); // => ['b', 'a', 'c']
swapIndices(['a', 'b', 'c'], 1, -1); // => ['c', 'b', 'a']
swapIndices('abc', 0, 1); // => 'bac'
dataThe item to be manipulated. This can be an array, or a string.index1The first index.index2The second index.ObjectData Last
swapIndices(index1, index2)(data);
swapIndices(0, 1)(['a', 'b', 'c']); // => ['b', 'a', 'c']
swapIndices(0, -1)('abc'); // => 'cba'
index1The first index.index2The second index.ObjectswapPropsSwaps the positions of two properties in an object based on the provided keys.
Data First
swap(data, key1, key2);
swap({ a: 1, b: 2, c: 3 }, 'a', 'b'); // => {a: 2, b: 1, c: 3}
dataThe object to be manipulated.key1The first property key.key2The second property key.ObjectData Last
swap(key1, key2)(data);
swap('a', 'b')({ a: 1, b: 2, c: 3 }); // => {a: 2, b: 1, c: 3}
key1The first property key.key2The second property key.ObjecttakeReturns the first n elements of array.
Data First
P.take(array, n);
P.take([1, 2, 3, 4, 3, 2, 1], 3); // => [1, 2, 3]
arrayThe array.nThe number of elements to take.ArrayData Last
P.take(n)(array);
P.pipe([1, 2, 3, 4, 3, 2, 1], P.take(n)); // => [1, 2, 3]
nThe number of elements to take.ObjecttakeFirstByTake the first n items from data based on the provided ordering criteria. This allows you to avoid sorting the array before taking the items. The complexity of this function is O(Nlogn) where N is the length of the array.
For the opposite operation (to drop n elements) see dropFirstBy.
Data First
P.takeFirstBy(data, n, ...rules);
P.takeFirstBy(['aa', 'aaaa', 'a', 'aaa'], 2, (x) => x.length); // => ['a', 'aa']
dataThe input array.nThe number of items to take. If `n` is non-positive no items would be returned, if `n` is bigger then data.length a *clone* of `data` would be returned.rulesA variadic array of order rules defining the sorting criteria. Each order rule is a projection function that extracts a comparable value from the data. Sorting is based on these extracted values using the native `<` and `>` operators. Earlier rules take precedence over later ones. Use the syntax `[projection, "desc"]` for descending order.ArrayData Last
P.takeFirstBy(n, ...rules)(data);
P.pipe(
['aa', 'aaaa', 'a', 'aaa'],
P.takeFirstBy(2, (x) => x.length),
); // => ['a', 'aa']
nThe number of items to take. If `n` is non-positive no items would be returned, if `n` is bigger then data.length a *clone* of `data` would be returned.rulesA variadic array of order rules defining the sorting criteria. Each order rule is a projection function that extracts a comparable value from the data. Sorting is based on these extracted values using the native `<` and `>` operators. Earlier rules take precedence over later ones. Use the syntax `[projection, "desc"]` for descending order.ObjecttakeLastTakes the last n elements from the array.
Data First
P.takeLast(array, n);
P.takeLast([1, 2, 3, 4, 5], 2); // => [4, 5]
arrayThe target array.nThe number of elements to take.ArrayData Last
P.takeLast(n)(array);
P.takeLast(2)([1, 2, 3, 4, 5]); // => [4, 5]
nThe number of elements to take.ObjecttakeLastWhileReturns elements from the end of the array until the predicate returns false. The returned elements will be in the same order as in the original array.
Data First
P.takeLastWhile(data, predicate);
P.takeLastWhile([1, 2, 10, 3, 4, 5], (x) => x < 10); // => [3, 4, 5]
dataThe array.predicateThe predicate.ArrayData Last
P.takeLastWhile(predicate)(data);
P.pipe(
[1, 2, 10, 3, 4, 5],
P.takeLastWhile((x) => x < 10),
); // => [3, 4, 5]
predicateThe predicate.ObjecttakeWhileReturns elements from the array until predicate returns false.
Data First
P.takeWhile(data, predicate);
P.takeWhile([1, 2, 3, 4, 3, 2, 1], (x) => x !== 4); // => [1, 2, 3]
dataThe array.predicateThe predicate.ArrayData Last
P.takeWhile(predicate)(data);
P.pipe(
[1, 2, 3, 4, 3, 2, 1],
P.takeWhile((x) => x !== 4),
); // => [1, 2, 3]
predicateThe predicate.ObjecttapCalls the given function with the given value, then returns the given value. The return value of the provided function is ignored.
This allows "tapping into" a function sequence in a pipe, to perform side effects on intermediate results.
Data First
P.tap(value, fn);
P.tap('foo', console.log); // => "foo"
valueThe value to pass into the function.fnThe function to call.ObjectData Last
P.tap(fn)(value);
P.pipe(
[-5, -1, 2, 3],
P.filter((n) => n > 0),
P.tap(console.log), // prints [2, 3]
P.map((n) => n * 2),
); // => [4, 6]
fnThe function to call.ObjecttimesCalls an input function n times, returning an array containing the results
of those function calls.
fn is passed one argument: The current value of n, which begins at 0
and is gradually incremented to n - 1.
Data First
P.times(count, fn);
P.times(5, identity()); //=> [0, 1, 2, 3, 4]
countA value between `0` and `n - 1`. Increments after each
function call.fnThe function to invoke. Passed one argument, the current value of
`n`.ObjecttoCamelCaseConvert a string to camel case.
toCamelCase(str);
toCamelCase('test'); // => 'test'
toCamelCase('test string'); // => 'testSTring'
toCamelCase('test string', { delimiter: '$' }); // => 'test$string'
toCamelCase('TestV2', { separateNumbers: true }); // => 'testV_2'
toCamelCase('__typename', { prefixCharacters: '_' }); // => '__typename'
toCamelCase('type__', { suffixCharacters: '_' }); // => 'type__'
toCamelCase('version 1.2.10', { mergeAmbiguousCharacters: true }); // => 'version1210'
inputthe string to convertoptionsOptional configuration for the conversion.stringtoCapitalCaseConvert a string to capital case.
toCapitalCase(str);
toCapitalCase('test'); // => 'Test'
toCapitalCase('test string'); // => 'Test String'
toCapitalCase('test string', { delimiter: '$' }); // => 'Test$String'
toCapitalCase('testV2', { separateNumbers: true }); // => 'TEST V 2'
toCapitalCase('__typename', { prefixCharacters: '_' }); // => '__Typename'
toCapitalCase('type__', { suffixCharacters: '_' }); // => 'Type__'
inputthe string to convertoptionsOptional configuration for the conversion.stringtoConstantCaseConvert a string to constant case.
toConstantCase(str);
toConstantCase('test'); // => 'TEST'
toConstantCase('test string'); // => 'TEST_STRING'
toConstantCase('test string', { delimiter: '$' }); // => 'TEST$STRING'
toConstantCase('testV2', { separateNumbers: true }); // => 'TEST_V_2'
toConstantCase('__typename', { prefixCharacters: '_' }); // => '__TYPENAME'
toConstantCase('type__', { suffixCharacters: '_' }); // => 'TYPE__'
inputthe string to convertoptionsOptional configuration for the conversion.stringtoKebabCasetoKebabCase(str);
toKebabCase('test'); // => 'test'
toKebabCase('test string'); // => 'test-string'
toKebabCase('test string', { delimiter: '$' }); // => 'test$string'
toKebabCase('testV2', { separateNumbers: true }); // => 'test-v-2'
toKebabCase('__typename', { prefixCharacters: '_' }); // => '__typename'
toKebabCase('type__', { suffixCharacters: '_' }); // => 'type__'
inputthe string to convertoptionsOptional configuration for the conversion.stringtoNoCaseConvert a string to space separated lower case.
toNoCase(str);
toNoCase('test'); // => 'test'
toNoCase('test string'); // => 'test string'
toNoCase('test string', { delimiter: '$' }); // => 'test$string'
toNoCase('testV2', { separateNumbers: true }); // => 'test v 2'
toNoCase('__typename', { prefixCharacters: '_' }); // => '__typename'
toNoCase('type__', { suffixCharacters: '_' }); // => 'type__'
inputthe string to convertoptionsOptional configuration for the conversion.stringtoPascalCaseConvert a string to pascal case.
toPascalCase(str);
toPascalCase('test'); // => 'Test'
toPascalCase('test string'); // => 'TestString'
toPascalCase('test string', { delimiter: '$' }); // => 'Test$String'
toPascalCase('testV2', { separateNumbers: true }); // => 'TestV_2'
toPascalCase('__typename', { prefixCharacters: '_' }); // => '__Typename'
toPascalCase('type__', { suffixCharacters: '_' }); // => 'Type__'
toPascalCase('version 1.2.10', { mergeAmbiguousCharacters: true }); // => 'Version1210'
inputthe string to convertoptionsOptional configuration for the conversion.stringtoPascalSnakeCaseConvert a string to kebab case.
toPascalSnakeCase(str);
toPascalSnakeCase('test'); // => 'Test'
toPascalSnakeCase('test string'); // => 'Test_String'
toPascalSnakeCase('test string', { delimiter: '$' }); // => 'Test$String'
toPascalSnakeCase('testV2', { separateNumbers: true }); // => 'Test_V_2'
toPascalSnakeCase('__typename', { prefixCharacters: '_' }); // => '__Typename'
toPascalSnakeCase('type__', { suffixCharacters: '_' }); // => 'Type__'
inputthe string to convertoptionsOptional configuration for the conversion.stringtoSentenceCasetoSentenceCase(str);
toSentenceCase('test'); // => 'Test'
toSentenceCase('test string'); // => 'Test string'
toSentenceCase('test string', { delimiter: '$' }); // => 'Test$String'
toSentenceCase('testV2', { separateNumbers: true }); // => 'Test v 2'
toSentenceCase('__typename', { prefixCharacters: '_' }); // => '__Typename'
toSentenceCase('type__', { suffixCharacters: '_' }); // => 'Type__'
inputthe string to convertoptionsOptional configuration for the conversion.stringtoSnakeCasetoSnakeCase(str);
toSnakeCase('test'); // => 'test'
toSnakeCase('test string'); // => 'test_string'
toSnakeCase('test string', { delimiter: '$' }); // => 'test$string'
toSnakeCase('testV2', { separateNumbers: true }); // => 'test_v_2'
toSnakeCase('__typename', { prefixCharacters: '_' }); // => '__typename'
toSnakeCase('type__', { suffixCharacters: '_' }); // => 'type__'
inputthe string to convertoptionsOptional configuration for the conversion.stringtoTrainCaseConvert a string to sentence case.
toTrainCase(str);
toTrainCase('test'); // => 'Test'
toTrainCase('test string'); // => 'Test-String'
toTrainCase('test string', { delimiter: '$' }); // => 'Test$String'
toTrainCase('testV2', { separateNumbers: true }); // => 'Test-V-2'
toTrainCase('__typename', { prefixCharacters: '_' }); // => '__Typename'
toTrainCase('type__', { suffixCharacters: '_' }); // => 'Type__'
inputthe string to convertoptionsOptional configuration for the conversion.stringuniqueReturns a new array containing only one copy of each element in the original list. Elements are compared by reference using Set.
Data First
P.unique(array);
P.unique([1, 2, 2, 5, 1, 6, 7]); // => [1, 2, 5, 6, 7]
dataThe array to filter.ObjectData Last
P.unique()(array);
P.pipe(
[1, 2, 2, 5, 1, 6, 7], // only 4 iterations
P.unique(),
P.take(3),
); // => [1, 2, 5]
ObjectuniqueByReturns a new array containing only one copy of each element in the original list transformed by a function. Elements are compared by reference using Set.
Data First
P.uniqueBy(data, keyFunction);
P.uniqueBy(
[{ n: 1 }, { n: 2 }, { n: 2 }, { n: 5 }, { n: 1 }, { n: 6 }, { n: 7 }],
(obj) => obj.n,
); // => [{n: 1}, {n: 2}, {n: 5}, {n: 6}, {n: 7}]
dataThe array to filter.keyFunctionExtracts a value that would be used to compare elements.ObjectData Last
P.uniqueBy(keyFunction)(data);
P.pipe(
[{ n: 1 }, { n: 2 }, { n: 2 }, { n: 5 }, { n: 1 }, { n: 6 }, { n: 7 }], // only 4 iterations
P.uniqueBy((obj) => obj.n),
P.take(3),
); // => [{n: 1}, {n: 2}, {n: 5}]
keyFunctionExtracts a value that would be used to compare elements.ObjectuniqueWithReturns a new array containing only one copy of each element in the original list. Elements are compared by custom comparator isEquals.
Data First
P.uniqueWith(array, isEquals);
P.uniqueWith(
[{ a: 1 }, { a: 2 }, { a: 2 }, { a: 5 }, { a: 1 }, { a: 6 }, { a: 7 }],
P.equals,
); // => [{a: 1}, {a: 2}, {a: 5}, {a: 6}, {a: 7}]
dataThe array to filter.isEqualsThe comparator.ObjectData Last
P.uniqueWith(isEquals)(array);
P.uniqueWith(P.equals)([
{ a: 1 },
{ a: 2 },
{ a: 2 },
{ a: 5 },
{ a: 1 },
{ a: 6 },
{ a: 7 },
]); // => [{a: 1}, {a: 2}, {a: 5}, {a: 6}, {a: 7}]
P.pipe(
[{ a: 1 }, { a: 2 }, { a: 2 }, { a: 5 }, { a: 1 }, { a: 6 }, { a: 7 }], // only 4 iterations
P.uniqueWith(P.equals),
P.take(3),
); // => [{a: 1}, {a: 2}, {a: 5}]
isEqualsThe comparator.ObjectvaluesReturns a new array containing the values of the array or object.
Data First
P.values(source);
P.values(['x', 'y', 'z']); // => ['x', 'y', 'z']
P.values({ a: 'x', b: 'y', c: 'z' }); // => ['x', 'y', 'z']
dataEither an array or an object.ObjectData Last
P.values()(source);
P.pipe(['x', 'y', 'z'], P.values()); // => ['x', 'y', 'z']
P.pipe({ a: 'x', b: 'y', c: 'z' }, P.values()); // => ['x', 'y', 'z']
P.pipe({ a: 'x', b: 'y', c: 'z' }, P.values(), P.first()); // => 'x'
ObjectzipCreates a new list from two supplied lists by pairing up equally-positioned items. The length of the returned list will match the shortest of the two inputs.
Data First
P.zip(first, second);
P.zip([1, 2], ['a', 'b']); // => [[1, 'a'], [2, 'b']]
firstThe first input list.secondThe second input list.ObjectData Last
P.zip(second)(first);
P.zip(['a', 'b'])([1, 2]); // => [[1, 'a'], [2, 'b']]
secondThe second input list.ObjectzipWithCreates a new list from two supplied lists by calling the supplied function with the same-positioned element from each list.
P.zipWith(fn)(first, second);
P.zipWith((a: string, b: string) => a + b)(['1', '2', '3'], ['a', 'b', 'c']); // => ['1a', '2b', '3c']
fnThe function applied to each position of the list.ObjectData Last
P.zipWith(second, fn)(first);
P.pipe(
['1', '2', '3'],
P.zipWith(['a', 'b', 'c'], (a, b) => a + b),
); // => ['1a', '2b', '3c']
secondThe second input list.fnThe function applied to each position of the list.ObjectData First
P.zipWith(first, second, fn);
P.zipWith(['1', '2', '3'], ['a', 'b', 'c'], (a, b) => a + b); // => ['1a', '2b', '3c']
firstThe first input list.secondThe second input list.fnThe function applied to each position of the list.Array