or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

algebraic.mdarray.mdeither.mdfunction.mdindex.mdio.mdoption.mdpipeable.mdrecord.mdtask-either.mdtask.mdtype-classes.md
tile.json

record.mddocs/

Record Operations

Record operations provide functional utilities for working with JavaScript objects as immutable records (dictionaries). Records are key-value maps where keys are strings and values are of a consistent type.

Core Imports

import { record } from "fp-ts/lib/Record";
import { isEmpty, size, lookup, has } from "fp-ts/lib/Record";

Capabilities

Basic Operations

Essential operations for working with records.

/**
 * Calculate the number of key/value pairs in a record
 * @param d - Record to measure
 * @returns Number of key/value pairs
 */
function size<A>(d: Record<string, A>): number;

/**
 * Test whether a record is empty
 * @param d - Record to test
 * @returns true if record has no keys
 */
function isEmpty<A>(d: Record<string, A>): boolean;

/**
 * Test whether a record has a key
 * @param k - Key to test for
 * @param d - Record to test
 * @returns true if key exists in record
 */
function has<A>(k: string, d: Record<string, A>): boolean;

/**
 * Lookup value by key, returning Option
 * @param k - Key to lookup
 * @param d - Record to search in
 * @returns Option containing value if key exists
 */
function lookup<A>(k: string, d: Record<string, A>): Option<A>;

Usage Examples:

import { size, isEmpty, has, lookup } from "fp-ts/lib/Record";

const person = { name: "Alice", age: 30 };

const recordSize = size(person); // 2
const empty = isEmpty({}); // true
const hasName = has("name", person); // true
const maybeName = lookup("name", person); // some("Alice")
const maybeEmail = lookup("email", person); // none

Record Construction and Modification

Create and modify records immutably.

/**
 * Create empty record
 */
const empty: Record<string, never>;

/**
 * Create record with single key-value pair
 * @param k - Key
 * @param a - Value
 * @returns Record with single entry
 */
function singleton<A>(k: string, a: A): Record<string, A>;

/**
 * Insert or update key-value pair
 * @param k - Key to insert
 * @param a - Value to insert
 * @param d - Record to modify
 * @returns New record with key-value pair added/updated
 */
function insert<A>(k: string, a: A, d: Record<string, A>): Record<string, A>;

/**
 * Remove key from record
 * @param k - Key to remove
 * @param d - Record to modify
 * @returns New record with key removed
 */
function remove<A>(k: string, d: Record<string, A>): Record<string, A>;

/**
 * Remove key and return both value and remaining record
 * @param k - Key to remove
 * @param d - Record to modify
 * @returns Option of tuple [value, remaining record]
 */
function pop<A>(k: string, d: Record<string, A>): Option<[A, Record<string, A>]>;

/**
 * Update value at key using function
 * @param k - Key to update
 * @param f - Function to transform value
 * @param d - Record to modify
 * @returns New record with value updated
 */
function modifyAt<A>(k: string, f: (a: A) => A, d: Record<string, A>): Record<string, A>;

/**
 * Update value at key
 * @param k - Key to update
 * @param a - New value
 * @param d - Record to modify
 * @returns Option of new record if key exists
 */
function updateAt<A>(k: string, a: A, d: Record<string, A>): Option<Record<string, A>>;

/**
 * Delete key at specific position
 * @param k - Key to delete
 * @param d - Record to modify
 * @returns Option of new record if key exists
 */
function deleteAt<A>(k: string, d: Record<string, A>): Option<Record<string, A>>;

Transformation Operations

Transform records using functional operations.

/**
 * Map over record values
 * @param f - Function to transform values
 * @param d - Record to transform
 * @returns New record with transformed values
 */
function map<A, B>(f: (a: A) => B, d: Record<string, A>): Record<string, B>;

/**
 * Map over record values with key information
 * @param f - Function receiving key and value
 * @param d - Record to transform
 * @returns New record with transformed values
 */
function mapWithIndex<A, B>(f: (k: string, a: A) => B, d: Record<string, A>): Record<string, B>;

/**
 * Collect record entries into array
 * @param f - Function to transform key-value pairs
 * @param d - Record to collect from
 * @returns Array of transformed entries
 */
function collect<A, B>(f: (k: string, a: A) => B, d: Record<string, A>): Array<B>;

/**
 * Convert record to array of key-value pairs
 * @param d - Record to convert
 * @returns Array of [key, value] tuples
 */
function toArray<A>(d: Record<string, A>): Array<[string, A]>;

/**
 * Get array of record keys
 * @param d - Record to get keys from
 * @returns Array of keys
 */
function keys<A>(d: Record<string, A>): Array<string>;

/**
 * Convert record to unfoldable structure
 * @param unfoldable - Unfoldable instance
 * @param d - Record to convert
 * @returns Unfoldable structure containing key-value pairs
 */
function toUnfoldable<F>(unfoldable: Unfoldable<F>): <A>(d: Record<string, A>) => HKT<F, [string, A]>;

Filtering Operations

Filter records based on predicates.

/**
 * Filter record by predicate on values
 * @param predicate - Predicate to test values
 * @param d - Record to filter
 * @returns New record containing only entries where predicate is true
 */
function filter<A>(predicate: Predicate<A>, d: Record<string, A>): Record<string, A>;
function filter<A, B extends A>(refinement: Refinement<A, B>, d: Record<string, A>): Record<string, B>;

/**
 * Filter record by predicate on keys and values
 * @param predicate - Predicate receiving key and value
 * @param d - Record to filter
 * @returns New record containing only entries where predicate is true
 */
function filterWithIndex<A>(predicate: PredicateWithIndex<string, A>, d: Record<string, A>): Record<string, A>;
function filterWithIndex<A, B extends A>(refinement: RefinementWithIndex<string, A, B>, d: Record<string, A>): Record<string, B>;

/**
 * Transform and filter record in one step
 * @param f - Function returning Option of transformed value
 * @param d - Record to transform and filter
 * @returns New record with transformed values where function returned Some
 */
function filterMap<A, B>(f: (a: A) => Option<B>, d: Record<string, A>): Record<string, B>;

/**
 * Transform and filter record with key information
 * @param f - Function receiving key and value, returning Option
 * @param d - Record to transform and filter
 * @returns New record with transformed values where function returned Some
 */
function filterMapWithIndex<A, B>(f: (k: string, a: A) => Option<B>, d: Record<string, A>): Record<string, B>;

/**
 * Partition record into two records based on predicate
 * @param predicate - Predicate to test values
 * @param d - Record to partition
 * @returns Separated object with left (false) and right (true) records
 */
function partition<A>(predicate: Predicate<A>, d: Record<string, A>): Separated<Record<string, A>, Record<string, A>>;
function partition<A, B extends A>(refinement: Refinement<A, B>, d: Record<string, A>): Separated<Record<string, A>, Record<string, B>>;

/**
 * Partition record with key information
 * @param predicate - Predicate receiving key and value
 * @param d - Record to partition
 * @returns Separated object with left (false) and right (true) records
 */
function partitionWithIndex<A>(predicate: PredicateWithIndex<string, A>, d: Record<string, A>): Separated<Record<string, A>, Record<string, A>>;

/**
 * Partition and transform record based on Either-returning function
 * @param f - Function returning Either
 * @param d - Record to partition and transform
 * @returns Separated object with left and right transformed records
 */
function partitionMap<A, B, C>(f: (a: A) => Either<B, C>, d: Record<string, A>): Separated<Record<string, B>, Record<string, C>>;

/**
 * Partition and transform record with key information
 * @param f - Function receiving key and value, returning Either
 * @param d - Record to partition and transform
 * @returns Separated object with left and right transformed records
 */
function partitionMapWithIndex<A, B, C>(f: (k: string, a: A) => Either<B, C>, d: Record<string, A>): Separated<Record<string, B>, Record<string, C>>;

Folding Operations

Reduce records to single values.

/**
 * Left fold over record values
 * @param b - Initial accumulator value
 * @param f - Folding function
 * @param d - Record to fold
 * @returns Final accumulated value
 */
function reduce<A, B>(b: B, f: (b: B, a: A) => B, d: Record<string, A>): B;

/**
 * Left fold with key information
 * @param b - Initial accumulator value
 * @param f - Folding function receiving key, accumulator, and value
 * @param d - Record to fold
 * @returns Final accumulated value
 */
function reduceWithIndex<A, B>(b: B, f: (k: string, b: B, a: A) => B, d: Record<string, A>): B;

/**
 * Right fold over record values
 * @param b - Initial accumulator value
 * @param f - Folding function
 * @param d - Record to fold
 * @returns Final accumulated value
 */
function reduceRight<A, B>(b: B, f: (a: A, b: B) => B, d: Record<string, A>): B;

/**
 * Right fold with key information
 * @param b - Initial accumulator value
 * @param f - Folding function receiving key, value, and accumulator
 * @param d - Record to fold
 * @returns Final accumulated value
 */
function reduceRightWithIndex<A, B>(b: B, f: (k: string, a: A, b: B) => B, d: Record<string, A>): B;

/**
 * Map each value to a monoid and combine results
 * @param M - Monoid instance for combining results
 * @param f - Function to map values to monoid
 * @param d - Record to fold
 * @returns Combined monoid value
 */
function foldMap<M>(M: Monoid<M>): <A>(f: (a: A) => M, d: Record<string, A>) => M;

/**
 * Map each key-value pair to a monoid and combine results
 * @param M - Monoid instance for combining results
 * @param f - Function to map key-value pairs to monoid
 * @param d - Record to fold
 * @returns Combined monoid value
 */
function foldMapWithIndex<M>(M: Monoid<M>): <A>(f: (k: string, a: A) => M, d: Record<string, A>) => M;

Set Operations

Operations treating records as sets.

/**
 * Test whether first record is subrecord of second
 * @param E - Equality instance for values
 * @param d1 - Potential sub-record
 * @param d2 - Potential super-record
 * @returns true if d1 is subrecord of d2
 */
function isSubrecord<A>(E: Eq<A>): (d1: Record<string, A>, d2: Record<string, A>) => boolean;

/**
 * Get union of two records (values from second record override first)
 * @param d1 - First record
 * @param d2 - Second record
 * @returns New record containing keys from both records
 */
function union<A>(d1: Record<string, A>, d2: Record<string, A>): Record<string, A>;

/**
 * Get intersection of two records
 * @param d1 - First record
 * @param d2 - Second record
 * @returns New record containing only keys present in both records
 */
function intersection<A>(d1: Record<string, A>, d2: Record<string, A>): Record<string, A>;

/**
 * Get difference of two records (keys in first but not second)
 * @param d1 - First record
 * @param d2 - Second record
 * @returns New record containing keys from d1 not in d2
 */
function difference<A>(d1: Record<string, A>, d2: Record<string, A>): Record<string, A>;

Type Class Instances

Record implements various type class instances.

/**
 * Equality instance for Record
 * @param E - Equality instance for values
 * @returns Equality instance that compares records key-wise
 */
function getEq<A>(E: Eq<A>): Eq<Record<string, A>>;

/**
 * Show instance for Record
 * @param S - Show instance for values
 * @returns Show instance that displays record contents
 */
function getShow<A>(S: Show<A>): Show<Record<string, A>>;

/**
 * Monoid instance for Record (union with semigroup for values)
 * @param S - Semigroup instance for values
 * @returns Monoid instance for records
 */
function getMonoid<A>(S: Semigroup<A>): Monoid<Record<string, A>>;

/**
 * Record instance providing Functor, Foldable, Traversable operations
 */
const record: FunctorWithIndex1<URI, string> &
  FoldableWithIndex1<URI, string> &
  TraversableWithIndex1<URI, string> &
  Compactable1<URI> &
  FilterableWithIndex1<URI, string> &
  Witherable1<URI>;

Common Patterns

Object Processing Pipeline

import { pipe } from "fp-ts/lib/pipeable";
import { map, filter, collect } from "fp-ts/lib/Record";

const users = {
  alice: { age: 25, active: true },
  bob: { age: 30, active: false },
  charlie: { age: 35, active: true }
};

const activeUserAges = pipe(
  users,
  filter((user) => user.active),
  map((user) => user.age),
  collect((name, age) => ({ name, age }))
);
// Result: [{ name: "alice", age: 25 }, { name: "charlie", age: 35 }]

Safe Object Access

import { lookup, map } from "fp-ts/lib/Record";
import { getOrElse } from "fp-ts/lib/Option";

const config = { host: "localhost", port: 3000 };

const host = pipe(
  lookup("host", config),
  getOrElse(() => "127.0.0.1")
);

const port = pipe(
  lookup("port", config),
  map(String),
  getOrElse(() => "8080")
);

Record Transformation and Validation

import { traverse } from "fp-ts/lib/Record";
import { option } from "fp-ts/lib/Option";
import { parseNumber } from "./utils";

const stringNumbers = { a: "1", b: "2", c: "not-a-number" };

const maybeNumbers = traverse(option)(parseNumber)(stringNumbers);
// Result: none (because "not-a-number" fails to parse)

const validNumbers = { a: "1", b: "2", c: "3" };
const parsedNumbers = traverse(option)(parseNumber)(validNumbers);
// Result: some({ a: 1, b: 2, c: 3 })

Types

// Record is the native JavaScript object type
// Used as Record<string, A> for objects with string keys and values of type A

// URI for type-level programming
const URI = 'Record';
type URI = typeof URI;

// Key constraint for records
type RecordKey = string;

// Separated type for partition operations
interface Separated<E, A> {
  left: E;
  right: A;
}

// Predicate and Refinement types
type Predicate<A> = (a: A) => boolean;
type Refinement<A, B extends A> = (a: A) => a is B;
type PredicateWithIndex<I, A> = (i: I, a: A) => boolean;
type RefinementWithIndex<I, A, B extends A> = (i: I, a: A) => a is B;