Skip to content

Rec

const Rec: object

Defined in: Data/Rec.ts:601

compact: <A>(data) => Readonly<Record<string, A>>

Removes all None values from a Record<string, Maybe<A>>, returning a plain Record<string, A>. Useful when building records from fallible lookups.

A

Readonly<Record<string, Maybe<A>>>

Readonly<Record<string, A>>

Rec.compact({ a: Maybe.make.some(1), b: Maybe.make.none(), c: Maybe.make.some(3) });
// { a: 1, c: 3 }

entries: <T>(data) => readonly readonly [keyof T, T[keyof T]][]

Returns all key-value pairs of a record.

T extends Record<string, unknown>

T

readonly readonly [keyof T, T[keyof T]][]

Rec.entries({ a: 1, b: 2 }); // [["a", 1], ["b", 2]]

filter: <A>(predicate) => (data) => Readonly<Record<string, A>>

Filters values in a record by a predicate.

A

(a) => boolean

(data) => Readonly<Record<string, A>>

pipe({ a: 1, b: 2, c: 3 }, Rec.filter(n => n > 1)); // { b: 2, c: 3 }

filterMap: <A, B>(f) => (data) => Readonly<Record<string, B>>

Maps each value in a record with a function returning a Maybe, keeping only Some values.

A

B

(a) => Maybe<B>

(data) => Readonly<Record<string, B>>

pipe(
  { a: 1, b: 2, c: 3 },
  Rec.filterMap((n) => (n % 2 === 0 ? Maybe.make.some(n * 10) : Maybe.make.none()))
); // { b: 20 }

filterWithKey: <A>(predicate) => (data) => Readonly<Record<string, A>>

Filters values in a record by a predicate that also receives the key.

A

(key, a) => boolean

(data) => Readonly<Record<string, A>>

pipe({ a: 1, b: 2, c: 3 }, Rec.filterWithKey((k, v) => k !== "a" && v > 0));
// { b: 2 }

from: object = RecFrom

entries: <A>(data) => Readonly<Record<string, A>>

Creates a record from key-value pairs.

A

readonly readonly [string, A][]

Readonly<Record<string, A>>

Rec.from.entries([["a", 1], ["b", 2]]); // { a: 1, b: 2 }

groupBy: <A>(keyFn) => (items) => Readonly<Record<string, readonly A[]>>

Groups elements of an array into a record keyed by the result of keyFn. Each key maps to the array of elements that produced it, in insertion order.

Unlike Dict.groupBy, keys are always strings. Use Dict.groupBy when you need non-string keys or want to avoid the plain-object prototype chain.

A

(a) => string

(items) => Readonly<Record<string, readonly A[]>>

pipe(
  ["apple", "avocado", "banana", "blueberry"],
  Rec.groupBy(s => s[0]),
); // { a: ["apple", "avocado"], b: ["banana", "blueberry"] }

is: object = RecIs

empty: <A>(data) => boolean

Returns true if the record has no keys.

A

Readonly<Record<string, A>>

boolean

Rec.is.empty({});       // true
Rec.is.empty({ a: 1 }); // false

nonEmpty: <A, K>(data) => data is NonEmptyRecord<A, K> = _isNonEmpty

Type guard to check if a record is non-empty.

A

K extends string

Readonly<Record<K, A>>

data is NonEmptyRecord<A, K>

Rec.is.nonEmpty({ a: 1 }); // true
Rec.is.nonEmpty({});       // false

keys: <T>(data) => readonly keyof T & string[]

Returns all keys of a record.

T extends Record<string, unknown>

T

readonly keyof T & string[]

Rec.keys({ a: 1, b: 2 }); // ["a", "b"]

lookup: <K>(key) => <V>(data) => Maybe<V>

Looks up a value by key, returning Maybe.

K extends string

K

<V>(data) => Maybe<V>

pipe({ a: 1, b: 2 }, Rec.lookup("a")); // Some(1)
pipe({ a: 1, b: 2 }, Rec.lookup("c")); // None

map: <A, B>(f) => <K>(data) => Readonly<Record<K, B>>

Transforms each value in a record.

A

B

(a) => B

<K>(data) => Readonly<Record<K, B>>

pipe({ a: 1, b: 2 }, Rec.map(n => n * 2)); // { a: 2, b: 4 }

mapEntries: <A, K2, B>(f) => (data) => Readonly<Record<K2, B>>

Transforms key and value pairs simultaneously.

A

K2 extends string

B

(key, value) => readonly [K2, B]

(data) => Readonly<Record<K2, B>>

pipe(
  { a: 1, b: 2 },
  Rec.mapEntries((k, v) => [k.toUpperCase(), v * 10])
); // { A: 10, B: 20 }

mapKeys: (f) => <A>(data) => Readonly<Record<string, A>>

Transforms each key while preserving values. If two keys map to the same new key, the last one wins.

(key) => string

<A>(data) => Readonly<Record<string, A>>

pipe({ firstName: "Alice", lastName: "Smith" }, Rec.mapKeys(k => k.toUpperCase()));
// { FIRSTNAME: "Alice", LASTNAME: "Smith" }

mapWithKey: <A, B>(f) => <K>(data) => Readonly<Record<K, B>>

Transforms each value in a record, also receiving the key.

A

B

(key, a) => B

<K>(data) => Readonly<Record<K, B>>

pipe({ a: 1, b: 2 }, Rec.mapWithKey((k, v) => `${k}:${v}`));
// { a: "a:1", b: "b:2" }

merge: <A>(other) => (data) => Readonly<Record<string, A>>

Merges two records. Values from the second record take precedence.

A

Readonly<Record<string, A>>

(data) => Readonly<Record<string, A>>

pipe({ a: 1, b: 2 }, Rec.merge({ b: 3, c: 4 })); // { a: 1, b: 3, c: 4 }

mergeWith: <A>(combine) => {(second): (first) => Readonly<Record<string, A>>; (first, second): Readonly<Record<string, A>>; }

Merges two records using a custom combination function on key collisions. Supports both uncurried Rec.mergeWith(combine)(first, second) and curried pipe(first, Rec.mergeWith(combine)(second)).

A

(a, b) => A

{(second): (first) => Readonly<Record<string, A>>; (first, second): Readonly<Record<string, A>>; }

const combineStats = Rec.mergeWith((a: number, b: number) => a + b);
combineStats({ a: 1, b: 2 }, { b: 3, c: 4 }); // { a: 1, b: 5, c: 4 }
pipe({ a: 1, b: 2 }, combineStats({ b: 3, c: 4 })); // { a: 1, b: 5, c: 4 }

NonEmpty: object = RecNonEmpty

entries: <K, A>(data) => NonEmptyArr<readonly [K, A]>

K extends string

A

NonEmptyRecord<A, K>

NonEmptyArr<readonly [K, A]>

from: object

Record: <K, A>(data) => Maybe<NonEmptyRecord<A, K>>

K extends string

A

Readonly<Record<K, A>>

Maybe<NonEmptyRecord<A, K>>

keys: <K, A>(data) => NonEmptyArr<K>

K extends string

A

NonEmptyRecord<A, K>

NonEmptyArr<K>

map: <A, B>(f) => <K>(data) => NonEmptyRecord<B, K>

A

B

(a) => B

<K>(data) => NonEmptyRecord<B, K>

mapWithKey: <A, B>(f) => <K>(data) => NonEmptyRecord<B, K>

A

B

(key, a) => B

<K>(data) => NonEmptyRecord<B, K>

reduce: <A>(f) => <K>(data) => A

A

(acc, a) => A

<K>(data) => A

singleton: <K, A>(key, value) => NonEmptyRecord<A, K>

K extends string

A

K

A

NonEmptyRecord<A, K>

values: <K, A>(data) => NonEmptyArr<A>

K extends string

A

NonEmptyRecord<A, K>

NonEmptyArr<A>

omit: <K>(…omittedKeys) => <A>(data) => Omit<A, K>

Omits specific keys from a record.

K extends string

K[]

<A>(data) => Omit<A, K>

pipe({ a: 1, b: 2, c: 3 }, Rec.omit("b")); // { a: 1, c: 3 }

pick: <K>(…pickedKeys) => <A>(data) => Pick<A, K>

Picks specific keys from a record.

K extends string

K[]

<A>(data) => Pick<A, K>

pipe({ a: 1, b: 2, c: 3 }, Rec.pick("a", "c")); // { a: 1, c: 3 }

sequence: object

Maybe: <A>(data) => Maybe<Readonly<Record<string, A>>> = RecMaybe.sequence

Sequence a record of Maybe values into a Maybe of a record. If any key contains None, the entire operation returns None.

A

Readonly<Record<string, Maybe<A>>>

Maybe<Readonly<Record<string, A>>>

Rec.sequence.Maybe({ a: Maybe.make.some(1), b: Maybe.make.some(2) }); // Some({ a: 1, b: 2 })
Rec.sequence.Maybe({ a: Maybe.make.some(1), b: Maybe.make.none() }); // None

Result: <E, A>(data) => Result<E, Readonly<Record<string, A>>> = RecResult.sequence

Sequence a record of Result values into a Result of a record. If any key contains an Err, the entire operation returns that Err.

E

A

Readonly<Record<string, Result<E, A>>>

Result<E, Readonly<Record<string, A>>>

Rec.sequence.Result({ a: Result.make.ok(1), b: Result.make.ok(2) }); // Ok({ a: 1, b: 2 })
Rec.sequence.Result({ a: Result.make.ok(1), b: Result.make.err("oops") }); // Err("oops")

size: <A>(data) => number

Returns the number of keys in a record.

A

Readonly<Record<string, A>>

number

Rec.size({ a: 1, b: 2 }); // 2

to: object = RecTo

Dict: <A, K>(data) => ReadonlyMap<K, A>

A

K extends string = string

Readonly<Record<K, A>>

ReadonlyMap<K, A>

traverse: object

Maybe: <A, B>(f) => (data) => Maybe<Readonly<Record<string, B>>> = RecMaybe.traverse

Map a function that returns a Maybe over each value of a record, and combine the results into a single Maybe containing the updated record. If any value results in None, the entire operation returns None (short-circuits).

A

B

(a) => Maybe<B>

(data) => Maybe<Readonly<Record<string, B>>>

const parseNum = (s: string) => s === "NaN" ? Maybe.make.none() : Maybe.make.some(Number(s));
pipe({ a: "1", b: "2" }, Rec.traverse.Maybe(parseNum)); // Some({ a: 1, b: 2 })
pipe({ a: "1", b: "NaN" }, Rec.traverse.Maybe(parseNum)); // None

Result: <E, A, B>(f) => (data) => Result<E, Readonly<Record<string, B>>> = RecResult.traverse

Map a function that returns a Result over each value of a record, and combine the results into a single Result containing the updated record. If any value results in an Err, the entire operation returns that Err (short-circuits).

E

A

B

(a) => Result<E, B>

(data) => Result<E, Readonly<Record<string, B>>>

const checkPositive = (n: number) => n < 0 ? Result.make.err("negative") : Result.make.ok(n);
pipe({ a: 1, b: 2 }, Rec.traverse.Result(checkPositive)); // Ok({ a: 1, b: 2 })
pipe({ a: 1, b: -2 }, Rec.traverse.Result(checkPositive)); // Err("negative")

updateIn: <T>(path, f) => (data) => Readonly<Record<string, unknown>>

Immutably updates a value at a deep nested path inside a record.

T

readonly [string, string]

(val) => T

(data) => Readonly<Record<string, unknown>>

pipe(
  { user: { profile: { age: 30 } } },
  Rec.updateIn(["user", "profile", "age"], (n: number) => n + 1)
); // { user: { profile: { age: 31 } } }

values: <T>(data) => readonly T[keyof T & string][]

Returns all values of a record.

T extends Record<string, unknown>

T

readonly T[keyof T & string][]

Rec.values({ a: 1, b: 2 }); // [1, 2]