Skip to content

Rec

Record utilities for working with plain JavaScript objects as dictionaries.

Provides type-safe operations for records (objects with PropertyKey indexes) including type guards, merging, creation, and index signature manipulation. Strictly validates plain objects, rejecting arrays and class instances.

Import

typescript
import { Rec } from '@wollybeard/kit'
typescript
import * as Rec from '@wollybeard/kit/rec'

Factories

[F] create

typescript
<value>(): Record<PropertyKey, value>

Returns: An empty record typed to hold values of the specified type

Create an empty record with a specific value type. Useful for initializing typed record collections.

Examples:

typescript
const 
scores
= create<number>()
scores
['alice'] = 95
scores
['bob'] = 87
// scores is typed as Record<PropertyKey, number>
typescript
// Creating typed lookups
interface User {
  
id
: string
name
: string
} const
userLookup
= create<User>()
userLookup
['u123'] = {
id
: 'u123',
name
: 'Alice' }
typescript
// Useful as accumulator in reduce operations
const 
grouped
= items.reduce(
(
acc
,
item
) => {
acc
[
item
.category] =
item
return
acc
}, create<
Item
>(),
)

Operations

[F] merge

typescript
<rec1 extends Any, rec2 extends Any > (rec1: rec1, rec2: rec2): rec1 & rec2

Parameters:

  • rec1 - The base record to merge into
  • rec2 - The record to merge from

Returns: A new record with properties from both records merged

Deep merge two records, with properties from the second record overwriting the first. This is an alias for Obj.merge that works specifically with record types.

Examples:

typescript
Rec
.merge({
a
: 1,
b
: 2 }, {
b
: 3,
c
: 4 })
// Returns: { a: 1, b: 3, c: 4 }
typescript
// Deep merging of nested records
Rec
.merge(
{
user
: {
name
: 'Alice',
settings
: {
theme
: 'dark' } } },
{
user
: {
settings
: {
fontSize
: 16 } } },
) // Returns: { user: { name: 'Alice', settings: { theme: 'dark', fontSize: 16 } } }
typescript
// Type-safe merging
type 
Config
= {
api
: {
url
: string };
timeout
?: number }
type
Overrides
= {
api
: {
key
: string };
timeout
: number }
const
config
:
Config
= {
api
: {
url
: 'https://api.com' } }
const
overrides
:
Overrides
= {
api
: {
key
: 'secret' },
timeout
: 5000 }
const
merge
d
=
Rec
.merge(
config
,
overrides
)
// merged is typed as Config & Overrides

Type Guards

[F] is

typescript
(value: unknown): boolean

Parameters:

  • value - The value to check

Returns: True if the value is a plain record object

Check if a value is a record (plain object only, not class instances or arrays). This is a strict check that only accepts plain objects with Object.prototype.

Examples:

typescript
Rec
.is({
a
: 1,
b
: 2 }) // true
Rec
.is({}) // true
Rec
.is([1, 2, 3]) // false - arrays are not records
Rec
.is(null) // false
Rec
.is(new
Date
()) // false - class instances are not plain records
Rec
.is(
Object
.
create
(null)) // false - not plain Object.prototype
typescript
// Type guard usage
function 
processData
(
data
: unknown) {
if (
Rec
.is(
data
)) {
// data is typed as Rec.Any
Object
.
keys
(
data
).
forEach
(
key
=> {
console
.
log
(
data
[
key
])
}) } }

Types

[T] Any

typescript
type Any = AnyKeyTo<unknown>

[T] AnyReadonly

typescript
type AnyReadonly = AnyReadonlyKeyTo<unknown>

[T] AnyKeyTo

typescript
type AnyKeyTo<$Value> = {
  [key: PropertyKey]: $Value
}

[T] AnyReadonlyKeyTo

typescript
type AnyReadonlyKeyTo<$Value> = {
  readonly [key: PropertyKey]: $Value
}

[T] Value

typescript
type Value = {
  [key: PropertyKey]: Lang.Value
}

[T] Optional

typescript
type Optional<$Key extends PropertyKey, $Value> = {
  [K in $Key]?: $Value
}

[T] RemoveIndex

typescript
type RemoveIndex<$T> = {
  [k in keyof $T as string extends k ? never : number extends k ? never : k]:
    $T[k]
}

Remove index signatures from an object type. Useful for converting Record types to object types with only known keys.

Examples:

typescript
type 
WithIndex
= {
a
: string;
b
: number; [
key
: string]: any }
type
WithoutIndex
=
RemoveIndex
<
WithIndex
> // { a: string; b: number }

[T] IsHasIndex

typescript
type IsHasIndex<$T, $Key extends PropertyKey = string> = $Key extends keyof $T
  ? true
  : false

Check if a type has an index signature.

Examples:

typescript
type 
T1
=
IsHasIndex
<{ [
key
: string]: any }> // true
type
T2
=
IsHasIndex
<{
a
: string }> // false
type
T3
=
IsHasIndex
<{ [
key
: number]: any }, number> // true