@unction/complete
v21.4.0
Published
The entirety of all unction fucntions
Downloads
16
Readme
unction.js
unction.js is a collection of many functions. THese functions are bound by a set of three principles that are detailed below.
Raison d'exister
There are a few similar libraries out there and they all have good standing with the community, so why make unctionjs? Well the original package started off as ramda-extra, a set of functions in a package that ramda seemed to never want to implement (like at the time mapKeys). Then eventually I got to the point where I wanted to have functions be curried for clarity and found that many ramda functions don't fully support only currying. While ramda is amazing and I still use it to this day I knew I had to fork off and write my own path.
Here's a list of (I believe) fair reasons why I don't use these popular and really good libraries:
- ramda: Ramda has all functions in a single package, it relies on internal private functions to ensure compatibility, does not have real type checking, prefers "autocurrying" which can lead to issues with curried functions, and finally as described above ramda has an interest in retaining a small surface layer.
- lodash: Lodash only does curried as a second class citizen, doesn't have type checking, prefers "autocurrying" when it has support for it, and doesn't have a very clear picture about what some of the functions are polymorphic.
That said every unctionjs function will work with every ramda and lodash function where currying is allowed.
Using unction libraries
You can install a package individually:
npm install --save @unction/treeify
import treeify from "@unction/treeify"
Or you can install the complete package:
npm install --save @unction/complete
and import the function from package:
import {treeify} from "@unction/complete"
Principle 1
All functions are curried. Due to the nature of functional programming it's exceedingly valuable to have functions that are, by default, curried. Here's an erxample:
// asStateTree.js
import treeify from "@unction/treeify"
import get from "@unction/get"
import dig from "@unction/dig"
import indexBy from "@unction/indexby"
import groupBy from "@unction/groupby"
export default treeify(
[
// Group by type
groupBy(get("type")),
// Index by id
indexBy(get("id")),
]
)
We can use this function like so:
// resources.js
import asStateTree from "./asStateTree"
// Take resources from the HTTP API, turn it into a state tree
pipe([fetchResources, asStateTree])
Principle 2
All functions know how to deal with a finite set of primitives. When using a unctionjs function you can be sure that we'll be able to handle all 6 enumerable types:
- Array
- Object
- Set
- Map
- String
- Stream (see: most.js)
Principle 3
All functions are pure by default. No function will ever have any side-effects (unless otherwise noted with a I
suffix like shuffleI()
) and are referentially transparent.
Principle 4
All functions are immutable by default. These functions do not mutate (unless otherwise noted with a M
suffix like appendM()
) the original values.
Functions
allObjectP()
StringRecord<string | number | symbol, T> => Promise<StringRecord<string | number | symbol, T>>
This takes an object where the values are probably promises and returns a promise that has that same object but with the resolved values.
Here's a good example of this function in use:
await allObjectP({
merge: mergeResource(session),
current: storeCurrent(session.id),
account: pullAccount(session.relationship.account.data.id, client),
})
// {merge, current, account}
If we use allP
or Promise.all
we're getting an array back, but that's annoying to destructure. The allObjectP
function gives us the concurrency we want with a named interface for the returned resolutions.
allP()
Array<T> => Promise<Array<T>>
A port of the Promise.all()
function.
Credit: @keithamus
allP([fetchUser, fetchToken])
always()
T => any => T
Always returns the value given when called
always(1)() // 1
always(1)(0) // 1
append()
A => OrderedArray<B> | Set<B> | Record<string | number | symbol, unknown> | Map<B, unknown> | string => Array<C> | string
Takes a value and puts it at the end of the given list.
append(4)([5]) // => [5, 4]
append("c")("ab") // => "abc"
NOTE: While there is a type annotation in the README, this function cannot have type annotations due to a bug in flow.
appendM()
A => Array<B> => Array<A | B>
Takes an array and an item and returns the combination of both, appended.
NOTE: This mutates the array
const data = [1, 2, 3]
appendM(4)(data)
Would return:
[1, 2, 3, 4]
applicator()
((A) => B) => A => B
Takes a function and a value and applies that function to that value.
applicator(inc)(1) // 1
applicators()
Array<MapperFunctionType<A, B>> | Set<MapperFunctionType<A, B>> | RecordType<C, MapperFunctionType<A, B>> => Record<string | number | symbol, A> | Map<C, A> => Record<string | number | symbol, B> | Map<C, B>
Takes a list of functions and a list of values and applies the values to the functions.
applicators([
recordfrom(["point", "x"]),
recordfrom(["point", "y"]),
recordfrom(["point", "z"]),
])([
40.453,
2.2,
423.0,
])
returns
[
{point: {x: 40.453}},
{point: {y: 2.2}},
{point: {z: 423.0}},
]
applicators({
x: inc,
y: dec
})({
x: -1,
y: 1
})
returns
{
x: 0,
y: 0
}
arrayify()
A => [A] | A
Takes a value and turns it into an array of that value, unless the value is already an array.
arrayify("a")
returns
["a"]
arrayify(["a"])
returns
["a"]
aside()
Array<MapperFunctionType<A, B>> => A => A
Takes a stack of functions, like pipe()
, but always returns the second argument.
pipe(
aside([(value) => value.toLowerCase(), console.log]),
processData
)(
"Hello, world"
) // "Hello, world"
But also logs:
"hello, world"
attach()
A => B => Record<string | number | symbol, B> | Map<A, B> => Record<string | number | symbol, B> | Map<A, B>
ObjectKeyType => ValueType => ObjectType => ObjectType
MapKeyType => ValueType => MapType => MapType
ArrayKeyType => ValueType => ArrayType => ArrayType
null => ValueType => SetType => SetType
null => ValueType => StreamType => StreamType
A polymorphic way to attach a value to the key on a keyed enumerator. When dealing with a sorted list type and the key is larger than the list, it will append to the list. When the key is an index that already exists it will place the value at that index and shift remaining values to the right.
attach("hello")("world")({}) // => {hello: "world"}
attach(3)("x")([1, 2, 3]) // => [1, 2, 3, "x"]
attach(1)("x")([1, 2, 3]) // => [1, "x", 2, 3]
attach(null)("x")(new Set([1, 2, 3])) // => {1 2 3 "x"}
attach(10)("x")([]) // => ["x"]
attach(0)("a")("bc") // => "abc"
attach(null)("a")(xstream.of("b")) // => a---b--=>
catchP()
MapperFunctionType<C, B> => Promise<A> => Promise<A | B>
A port of the Promise.prototype.catch()
function.
catchP(
(exception) => console.error(exception)
)(Promise.all([fetchUser, fetchProject]))
Credit: @keithamus
compact()
ListType<A | null> | RecordType<unknown, A | null> => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Takes a collection (Array or Object) and returns a copy of that value without null
or undefined
values.
avatarUrls // => [null, "/1.jpg", null, "/3.jpg"]
compact(avatarUrls) // => ["/1.jpg", "/3.jpg"]
user // {"avatar": null, "name": "Kurtis Rainbolt-Greene"}
compact(head(user)) // {"name": "Kurtis Rainbolt-Greene"}
compose()
Array<A> => B => C
Takes a list of functions and runs a value through that stack from right to left.
compose([toInteger, toString])(0) // 0
compose([append("b"), append("a")])("c") // "cab"
computedProp()
MapperFunctionType<A, B> => KeyChainType<C> => Array<A> | Set<A> | RecordType<C | B, A> | string => Array<A> | Set<A> | RecordType<C | B, A> | string
Given an object this function will return that object but with a new property, where the value is computed. The computation is given the object you'll be copying.
const computer = ({id, attributes: {username}}) => `${username}#${id}`
const key = "tag"
const payload = {
id: "1",
attributes: {
username: "krainboltgreene"
}
}
computedProp(computer)(key)(payload)
Would return:
{
id: "1",
tag: "krainboltgreene#1",
attributes: {
username: "krainboltgreene"
}
}
const multiKey = ["attributes", "tag"]
computedProp(computer)(key)(payload)
Would return:
{
id: "1",
attributes: {
tag: "krainboltgreene#1",
username: "krainboltgreene"
}
}
couple()
L => R => [L, R]
Takes any value and then any value and returns an array containing those values.
couple(4)(5) // => [4, 5]
dig()
Array<A> => B => C
Takes a chain of keys and a tree, traversing down and reaching the last value. If any part of the chain is undefined or not an object the result will always be undefined.
dig(["aaa", "bbb", "ccc"])({aaa: {bbb: {ccc: "1"}}}) // "1"
dig(["aaa", "ddd", "ccc"])({aaa: {bbb: {ccc: "1"}}}) // undefined
domEvents()
DOMEventsConfigurationType => DOMEventNameType => DOMStreamType => DOMEventStreamType
Takes a configuration, an event name, and a DOM source and returns an observable of that event type
domEvents({})("click")(DOM)
returns
--click--click--click-=>
domEventsMany()
DOMEventsManyConfigurationType => Array<DOMEventNameType> => DOMEventStreamType
Takes many event names and returns an observable of those events.
domEventsMany({})(["click", "input"])(DOM)
returns
--click--input--input--click--input--|
dropFirst()
number => OrderedArray<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => OrderedArray<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Returns all but the first N of a list of ordered values.
dropFirst(2)([1, 2, 3]) // [3]
dropFirst(1)([1, 2, 3]) // [2, 3]
dropFirst(2)("abc") // "c"
dropFirst(1)("abc") // "bc"
dropLast()
number => OrderedArray<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => OrderedArray<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Returns all but the last N of a list of ordered values.
dropLast(2)([1, 2, 3]) // [1]
dropLast(1)([1, 2, 3]) // [1, 2]
dropLast(2)("abc") // "a"
dropLast(1)("abc") // "ab"
endsWith()
string => string => boolean
Determines if a given subset of text is at the end of another set of text.
endsWith("!")("Hello, world!") // true
equals()
L => R => boolean
Compares two values and attempts to discern if they are truly equal.
equals(true)(true) // true
equals([1, 2, 3])([1, 2, 3]) // true
equals({aaa: "aaa", bbb: "bbb"})({aaa: "aaa", bbb: "bbb"}) // true
equals("abc")("abc") // true
equals(null)(null) // true
equals(undefined)(undefined) // true
equals(false)(true) // false
equals([1, 2, 3])([3, 2, 1]) // false
equals([1, 2, 3])([1]) // false
equals([1, 2, 3])([]) // false
equals({aaa: "aaa", bbb: "bbb"})({aaa: "aaa"}) // false
equals({aaa: "aaa", bbb: "bbb"})({}) // false
equals({aaa: "aaa", bbb: "bbb"})({aaa: "bbb", bbb: "ccc"}) // false
equals("abc")("bac") // false
equals(null)(undefined) // false
equals(undefined)(null) // false
everyP()
Array<Promise<A>> => Promise<[Array<A>, Array<B>]>
Returns both resolved and rejected promises as distinct lists.
exceptKey()
B => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Takes a key and a keyed functor, returning the keyed functor without the key given.
exceptKey(1)([1, 2, 3]) // [1, 3]
exceptKey(1)("abc") // "ac"
exceptKey("aaa")({aaa: "aaa", bbb: "bbb", ccc: "ccc"}) // {bbb: "bbb", ccc: "ccc"}
exceptKey("aaa")(new Map([["aaa", "aaa"], ["bbb", "bbb"], ["ccc", "ccc"]])) // new Map([["bbb", "bbb"], ["ccc", "ccc"]])
first()
OrderedArray<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => A | string | void
Returns the first item of an ordered list.
first([1, 2, 3]) // 1
first("abc") // "a"
flatten()
ListType<Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string | A> | RecordType<unknown, Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string | A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Takes a multi-dimensional enumerable and decreases the nesting by one.
import {from} from "most"
flatten([["a", "b"], ["c", "d"]]) // ["a", "b", "c", "d"]
flatten(["a", "b", ["c", "d"]]) // ["a", "b", "c", "d"]
flatten(
from([
from(["a", "b"]),
from(["c", "d"]),
])
) // ---a---b---c---d---|
flattenTree()
string => Record<string | number | symbol, B> | Map<A, B> => Record<string | number | symbol, B> | Map<A, B>
Takes a tree and creates a single object where the root keys are conjoined nested keys.
flattenTree(
"-"
)(
{
data: {
profile: {
name: "Kurtis Rainbolt-Greene",
age: 24,
},
metadata: {
interval: "10s",
},
location: "http://api.example.com/profiles/24",
}
}
)
Would return:
{
"data-profile-name": "Kurtis Rainbolt-Greene",
"data-profile-age": 24,
"data-metadata-interval": "10s",
"data-location": "http://api.example.com/profiles/24"
}
flip()
MapperFunctionType<A, MapperFunctionType<B, C>> => B => A => C
Flips a function's first and second arguments.
flip(key)({aaa: "1"})("aaa") // "1"
forEach()
MapperFunctionType<A, B> => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Takes any kind of enumerable and figures out the best way to iterate over it.
forEach((x) => y)([])
forEach((x) => y)(new Map)
forEach((x) => y)({})
fresh()
A => A
Takes a value and returns an empty fresh version of that value.
fresh({aaa: "aaa"}) // {}
fresh(["aaa"]) // []
fresh({}) // {}
fresh([]) // []
fromArrayToObject()
Array<[string | number, A]> => ObjectType<A>
Takes an array that looks like a primitive Object and turns it into a proper object. Duplicate keys get overwritten.
fromArrayToObject([["aaa", "1"], ["bbb", "2"]]) // {aaa: 1, bbb: 2}
fromFunctorToPairs()
NOTE: This library has been deprecated in favor of unction/pairsFrom
FunctorType => Array<[KeyType?, ValueType?]>
Takes a functor and tries to transform it into a list of key-value pairs.
fromFunctorToPairs({aaa: "a", bbb: "b", ccc: "c"})) // [["aaa", "a"], ["bbb", "b"], ["ccc", "c"]]
fromFunctorToPairs(["a", "b", "c"]) // [[0, "a"], [1, "b"], [2, "c"]]
fromFunctorToPairs(new Map([["aaa", "a"], ["bbb", "b"], ["ccc", "c"]])) // [["aaa", "a"], ["bbb", "b"], ["ccc", "c"]]
fromFunctorToPairs(new Set(["a", "b", "c"])) // [[undefined, "a"], [undefined, "b"], [undefined, "c"]]
fromIteratorToArray()
Map<A, B> => Array<[A, B]>
Takes an Iterator (SetIterator, MapIterator, etc) and turns it into an array.
fromIteratorToArray(new Set([1, 2, 3]).entries()) // [[1, 1], [2, 2], [3, 3]]
fromIteratorToArray(new Map([["aaa", "a"], ["bbb", "b"], ["ccc", "c"]]).entries()) // [["aaa", "a"], ["bbb", "b"], ["ccc", "c"]]
get()
KeyType => unknown => ValueType
Returns the value of a specific key on an iterable. If no key is found it returns undefined. If the second argument isn't an iterable we return undefined, to allow for graceful failure.
get("aaa")({aaa: "1"}) // "1"
get("bbb")({aaa: "1"}) // undefined
get("bbb")(undefined) // undefined
get(0)(["aaa"]) // "aaa"
getMany()
Array<A> => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<B>
Takes a list of keys and a keyed enumerable, and returns the values for those keys. If no key exists, the value is undefined.
getMany(["aaa", "bbb"])({aaa: "111", bbb: "222"}) // ["111", "222"]
getMany(["aaa", "ccc"])({aaa: "111", bbb: "222"}) // ["111", undefined]
greaterThan()
number => number => boolean
Determines if one number is greater than another number.
greaterThan(1)(0) // true
greaterThan(0)(1) // false
groupBy()
MapperFunctionType<A, B> => Array<A> | Set<A> => Map<B, Array<A> | Set<A>>
Creates a record tree where the key is a computation on the value and the value is a list of the values that match with that computation.
groupBy(
key("type")
)([
{
id: "aaa",
name: "Kurtis Rainbolt-Greene",
type: "person",
},
{
id: "bbb",
name: "Angela Rainbolt-Greene",
type: "person",
},
])
Which returns:
Map {
"person" => [
{
id: "aaa",
name: "Kurtis Rainbolt-Greene",
type: "person",
},
{
id: "bbb",
name: "Angela Rainbolt-Greene",
type: "person",
},
],
}
groupBy(
key("type")
)(
Set [
Map {
"id" => "aaa",
"name" => "Kurtis Rainbolt-Greene"
"type" => "person",
},
Map {
"id" => "bbb",
"name" => "Angela Rainbolt-Greene"
"type" => "person",
}
]
)
Which returns:
Map {
"person" => Set [
Map {
"id" => "aaa",
"name" => "Kurtis Rainbolt-Greene",
"type" => "person",
},
Map {
"id" => "bbb",
"name" => "Angela Rainbolt-Greene",
"type" => "person",
}
],
}
hammer()
A => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Use this to de-nest a nested keyed enumerable.
const payload = {
id: 1
attributes: {
name: "Kurtis Rainbolt-Greene",
age: 26
}
}
hammer("attributes")(payload)
Which returns:
{
id: 1,
name: "Kurtis Rainbolt-Greene",
age: 26
}
ifThenElse()
PredicateFunctionType<A> => MapperFunctionType<A, B> => MapperFunctionType<A, C> => B | C
Based on a predicate it passes the value to a consequent or alternative function
ifThenElse(isEven)(toString)(toFloat)(1) // 1.0
ifThenElse(isEven)(toString)(toFloat)(2) // "2"
indexBy()
MapperFunctionType<A, B> => Array<A> | Set<A> => Map<B, A>
Creates a record tree where the key is a computation on the value and the value is the original value.
indexBy(
key("id")
)([
{
id: "aaa",
name: "Kurtis Rainbolt-Greene",
},
{
id: "bbb",
name: "Angela Rainbolt-Greene",
},
])
Which returns:
{
aaa: {
id: "aaa",
name: "Kurtis Rainbolt-Greene",
},
bbb: {
id: "bbb",
name: "Angela Rainbolt-Greene",
},
}
indexBy(
key("id")
)(
new Set([
new Map([
["id", "aaa"],
["name", "Kurtis Rainbolt-Greene"]
]),
new Map([
["id", "bbb"],
["name", "Angela Rainbolt-Greene"]
])
])
)
Which returns:
new Map([
["aaa", new Map([
["id", "aaa"],
["name", "Kurtis Rainbolt-Greene"]
])],
["bbb", new Map([
["id", "bbb"],
["name", "Angela Rainbolt-Greene"]
])],
])
inflateTree()
string => Record<string | number | symbol, B> | Map<A, B> => RecordType<A, C>
Takes a flat record with a specific key pattern and turns it into a nested record.
inflateTree(
"-"
)(
{
"data-profile-name": "Kurtis Rainbolt-Greene",
"data-profile-age": 24,
"data-metadata-interval": "10s",
"data-location": "http://api.example.com/profiles/24",
}
)
which returns
{
data: {
profile: {
name: "Kurtis Rainbolt-Greene",
age: 24,
},
metadata: {interval: "10s"},
location: "http://api.example.com/profiles/24",
},
}
initial()
OrderedArray<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => OrderedArray<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Returns all but the last item in an ordered list.
initial([1, 2, 3]) // [1, 2]
initial("abc") // "ab"
isArray()
A => boolean
Takes any value and then any value and returns an array containing those values.
isArray([]) // => true
isArray({}) // => false
isArray("") // => false
isEnumerable()
A => Boolean
Determines if the value is an enumerable and if so returns true, else false.
isEnumerable(1) // false
isEnumerable("") // true
isEnumerable([]) // true
isEnumerable({}) // true
isEnumerable(new Map()) // true
isEnumerable(new Set()) // true
isEnumerable(most.from([])) // true
isEnumerable(most.from([])) // true
isNil()
A => boolean
Determines if a value is not a value.
isNil(null) // true
isNil(undefined) // true
isNil(0) // false
isNil("") // false
isNil([]) // false
isNil({}) // false
isObject()
A => boolean
Takes a value and determines if it's an object.
isObject({}) // => true
isObject([]) // => false
isObject("") // => false
isPopulated()
Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => boolean
Allows you to check if a enumerable has any items.
isPopulated([1]) // true
isPopulated({a: 'b'}) // true
isPopulated({}) // false
isPopulated([]) // false
isPopulated("") // false
isPopulated("a") // true
isPresent()
A => boolean
This lets you know if it's a non-null, non-undefined value.
isPresent('x') // true
isPresent([]) // true
isPresent(null) // false
isPresent(undefined) // false
isType()
string => A => boolean
Takes any value and then any value and returns an array containing those values.
isType("Object")({}) // => true
isType("Array")([]) // => true
isType("String")("") // => true
itself()
A => A
Always returns the value given when calling.
itself(1) // 1
itself(1) // 1
keyChainTree()
Record<string | number | symbol, B> | Map<A, B> => Array<KeyChainType<A>>
Takes a tree and returns all keychains for that tree. Note, it only follows record types (types with keys).
keyChainTree({
id: "1",
attributes: {
name: "Kurtis Rainbolt-Greene",
age: 24,
},
meta: new Map([
["version", "1.0.0"],
]),
included: [
{
id: "2",
attributes: {
name: "Angela Englund",
},
},
],
})
which would return
[
["id"],
["attributes", "name"],
["attributes", "age"],
["meta", "version"],
["included"],
]
keys()
Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<B>
Takes a keyed iterable and returns the keys as an Array.
keys({aaa: "111", bbb: "222"}) // ["aaa", "bbb"]
keys(["111", "222"]) // [0, 1]
lacksText()
string => string => boolean
Determines if a set of text does not have a subset of text.
const data = "I love pies!"
const lacksBestFood = lacksText("pizza")
lacksBestFood(data) // false
last()
OrderedArray<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => A
Returns the last item of an ordered list.
last([1, 2, 3]) // 3
last("abc") // "c"
length()
Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => number
Returns the number of values contained in the enumerable.
length([1, 2, 3]) // 3
length({aaa: "aaa", bbb: "bbb"}) // 2
length(new Map([["aaa", "aaa"], ["bbb", "bbb"]])) // 2
length(new Set([1, 2, 3])) // 3
lessThan()
number => number => boolean
Determines if one number is greater than another number.
lessThan(0)(1) // true
lessThan(1)(0) // false
mapKeys()
MapperFunctionType<A, B> => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => KeyedArray<B> | Set<B> | Record<string | number | symbol, unknown> | Map<B, unknown> | string
Map over a keyed functor's keys and return a new keyed functor having mapped the keys
const attributes = {
name: "Kurtis Rainbolt-Greene",
createdAt: new Date()
}
mapKeys(kebab)(attributes)
Would return:
{
name: "Kurtis Rainbolt-Greene",
"created-at": new Date()
}
mapKeysWithValueKey()
MapperFunctionType<A, MapperFunctionType<B, C>> =>
Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string =>
Array<B> | Set<B> | Record<string | number | symbol, B> | Map<C, B> | string
Map over keys with the context of the value and key.
const attributes = {
name: "Kurtis Rainbolt-Greene",
createdAt: new Date()
}
mapKeys((value) => (key) => )(attributes)
Would return:
{
name: "Kurtis Rainbolt-Greene",
"created-at": new Date()
}
mapValues()
MapperFunctionType<A, B> => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<B> | Set<B> | Record<string | number | symbol, unknown> | Map<B, unknown> | string
A pretty standard mapValues()
, but with enforced unary currying.
mapValues(
(value) => value + 1
)(
[1, 2, 3]
)
Which will return:
[2, 3, 4]
mapValuesWithValueKey()
MapperFunctionType<A, MapperFunctionType<B, C>> =>
Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string =>
Array<B> | Set<B> | Record<string | number | symbol, B> | Map<C, B> | string
Just like map, but gives back the index argument (as an integer, not a string if array)
mergeAllLeft()
Array<Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string> => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Merges a list of enumerables (of the same type) into a single enumerable.
mergeAllLeft([["0"], ["1"], ["2"]]) // ["2", "1", "0"]
mergeAllLeft([{aaa: "aaa"}, {bbb: "bbb"}, {ccc: "ccc"}]) // {aaa: "aaa", bbb: "bbb", ccc: "ccc",}
mergeAllRight()
Array<Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string> => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Merges a list of enumerables (of the same type) into a single enumerable.
mergeAllRight([["0"], ["1"], ["2"]]) // ["0", "1", "2"]
mergeAllRight([{aaa: "aaa"}, {bbb: "bbb"}, {ccc: "ccc"}]) // {aaa: "aaa", bbb: "bbb", ccc: "ccc",}
mergeDeepLeft()
Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Recursively merges two enumerables. Merges objects with merge
and arrays with concat. Prefers left. THAT IS ALL.
const left = {
alpha: "1"
}
const right = {
beta: "2"
}
mergeDeepLeft(left)(right)
{
alpha: "1",
beta: "2"
}
const left = {
alpha: {
alpha1: "1"
}
}
const right = {
beta: {
beta1: "1"
}
}
mergeDeepLeft(left)(right)
{
alpha: {
alpha1: "1"
},
beta: {
beta1: "1"
}
}
const left = {
alpha: [
"1"
]
}
const right = {
alpha: [
"1"
]
}
mergeDeepLeft(left)(right)
{
alpha: [
"1",
"1"
]
}
mergeDeepRight()
Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Recursively merges two enumerables. Merges objects with merge
and arras with concat. Prefers right. THAT IS ALL.
const left = {
alpha: "1"
}
const right = {
beta: "2"
}
mergeDeepRight(left)(right)
{
alpha: "1",
beta: "2"
}
const left = {
alpha: {
alpha1: "1"
}
}
const right = {
beta: {
beta1: "1"
}
}
mergeDeepRight(left)(right)
{
alpha: {
alpha1: "1"
},
beta: {
beta1: "1"
}
}
const left = {
alpha: [
"1"
]
}
const right = {
alpha: [
"1"
]
}
mergeDeepRight(left)(right)
{
alpha: [
"1",
"1"
]
}
mergeLeft()
Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Merges two enumerables, preferring left.
const left = {
alpha: "1",
beta: "1"
}
const right = {
beta: "2",
zeta: "3"
}
mergeLeft(left)(right)
Which returns:
{
alpha: "1",
beta: "1",
zeta: "3"
}
mergeRight()
Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Merges two enumerables, preferring right.
const left = {
alpha: "1",
beta: "1"
}
const right = {
beta: "2",
zeta: "3"
}
mergeRight(left)(right)
Which returns:
{
alpha: "1"
beta: "2",
zeta: "3"
}
mergeWith()
MapperFunctionType<A, MapperFunctionType<A, A>> => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Merges two enumerables and uses a provided function to handle conflicts. The function is given the the left value and the right value.
const left = {
alpha: "0",
beta: "1",
zeta: "3"
}
const right = {
alpha: "0",
beta: "2",
zeta: "3"
}
mergeWith((l) => (r) => l+r)(left)(right)
Which returns:
{
alpha: "0",
beta: "12",
zeta: "3"
}
mergeWithKey()
MapperFunctionType<L, MapperFunctionType<R, MapperFunctionType<K, V>>> =>
KeyedEnumerableType<R, K> =>
KeyedEnumerableType<L, K> =>
ListType<V> | Record<string | number | symbol, V> | Map<K, V> | string
Merges two keyed enumerables and uses a function to handle conflicts. The function is given the left value, the right value, and the key.
const left = {
beta: "1"
}
const right = {
beta: "2"
}
mergeWithKey((left) => (right) => (key) => key+leftValue+rightValue)(left)(right)
Which returns:
{
beta: "beta12"
}
nestedApply()
(MapperFunctionType<A, B> => Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string => Array<B> | Set<B> | Record<string | number | symbol, unknown> | Map<B, unknown> | string) =>
MapperFunctionType<A, B> =>
number =>
Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string =>
Array<A> | Set<A> | Record<string | number | symbol, B> | Map<B, A> | string
Takes a function (the application) that takes function(s) (later referred to as
the inner) and value(s) (mapValues()
, forEach()
, selectValues()
), a function (the inner)
that will be applied to a value(s), and finally a number (depth) to apply that
applicator around the inner.
In the below example we want to take two sets of records and index them by id:
const records = [
[
{
id: "a1",
type: "commercial",
},
{
id: "a2",
type: "commercial",
}
],
[
{
id: "b1",
type: "residential",
},
{
id: "b2",
type: "residential",
}
]
]
Normally we'd just do mapValues(indexBy(key("id")))
, however we can make this easier and dynamic:
const nestedIndexById = nestedApply(mapValues)(indexBy(key("id")))(1)
nestedIndexById(records)
And the result:
[
{
a1: {
id: "a1",
type: "commercial",
},
a2: {
id: "a2",
type: "commercial",
},
},
{
b1: {
id: "b1",
type: "residential",
},
b2: {
id: "b2",
type: "residential",
},
},
]
objectFrom()
KeyChainType<A> => B => ObjectType<B>
Given a keychain and a value it creates an object that has keys bas