Rec — Record Utilities
Plain JavaScript objects serving as dictionaries — typed as Record<string, A> — are the most
ubiquitous data structures in any TypeScript application. We use them for configurations, lookup
tables, and serialized payloads.
However, working with records in functional pipelines introduces two common points of friction:
- They are data-first: Modifying objects natively forces us to write verbose, inline spreads
inside our
pipechains:(obj) => ({ ...obj, key: value }). - They are unsafe: Accessing a missing key via bracket notation (
obj[key]) silently returnsundefinedat runtime, bypassing the type system and causing errors downstream.
Rec solves both issues. It provides a small, highly optimized collection of data-last, curried
utilities designed to compose cleanly in pipelines, returning explicit Maybe values for safe,
crash-free key lookups.
Safe Key Lookup
Section titled “Safe Key Lookup”Rec.lookup retrieves the value associated with a key, wrapping it in a Maybe container to make
key absence explicit in your types:
This integrates naturally with other pipelines:
Transforming Values
Section titled “Transforming Values”Rec.map transforms every value inside a record, returning a new record with the original keys
preserved:
If the transformation requires the key as well as the value, Rec.mapWithKey passes both to your
callback:
Filtering Values
Section titled “Filtering Values”Rec.filterkeeps only the entries whose values satisfy a predicate.Rec.filterWithKeypasses both the key and the value to the predicate:
Picking and Omitting Keys
Section titled “Picking and Omitting Keys”Rec.pickreturns a new record containing only the specified keys.Rec.omitreturns a new record with the specified keys removed.
Both utilities are fully type-safe. pick returns a precise Pick<A, K> type and omit
returns a precise Omit<A, K> type, ensuring the compiler tracks exactly which properties survive
the pipeline:
Merging Records
Section titled “Merging Records”Rec.merge combines two records, returning a fresh object. Keys present in the second record
override those in the first record, behaving identically to standard object spreads:
Keys, Values, and Entries
Section titled “Keys, Values, and Entries”Rec provides utilities to extract arrays of keys, values, or entries:
Rec.fromEntries is the inverse constructor, building a record from an array of key-value pairs:
You can pair entries and fromEntries to easily perform structural record mappings:
Sizing and Verification
Section titled “Sizing and Verification”When to use Rec
Section titled “When to use Rec”Use Rec when:
Section titled “Use Rec when:”- Operating inside pipelines: You are transforming, filtering, or merging records point-free
inside
pipechains. - You require type-safe picks or omits: You want the compiler to statically track exactly which properties exist after keys are picked or omitted.
- Safe key retrieval is required: You want to avoid accidental
undefinedruntime crashes by capturing key absence as aMaybecontainer.
Keep using standard object notation when:
Section titled “Keep using standard object notation when:”- The operation is a simple, local one-liner: Inside a narrow function body where standard
dot-notation
obj.keyor spreads{ ...obj }are already clear and require no composition.