Type guard that checks if a value is a record — a non-null, non-array
object — and narrows it to UnknownRecord (= ReadonlyRecord<string, unknown>).
This function is designed to be combined with hasKey to probe
values of type unknown (e.g. parsed JSON, caught errors, external data)
in a type-safe way: if (isRecord(u) && hasKey(u, 'some-key')) { ... }.
Type Narrowing Behavior:
Narrows unknown to UnknownRecord (= ReadonlyRecord<string, unknown>)
Excludes null, undefined, primitives, and functions
Excludes arrays: arrays have no string index signature, so they are not
assignable to UnknownRecord; admitting them at runtime would be
inconsistent with the narrowed type
Returns true for every other non-null object, including dictionary
objects created with Object.create(null) and instances such as Date,
RegExp, Map, Set, Error, and user-defined classes
Why non-plain objects are included: since every property of
UnknownRecord is typed unknown, reading properties from any object
through this narrowing is type-safe, and hasKey (backed by
Object.hasOwn) answers own-property questions correctly on any object
(e.g. Map entries are not own properties, so hasKey correctly returns
false for them). Restricting the guard to plain objects would require
prototype checks that misjudge cross-realm objects and would prevent
probing useful instances such as Error subclasses.
Type guard that checks if a value is a record — a non-null, non-array object — and narrows it to
UnknownRecord(=ReadonlyRecord<string, unknown>).This function is designed to be combined with hasKey to probe values of type
unknown(e.g. parsed JSON, caught errors, external data) in a type-safe way:if (isRecord(u) && hasKey(u, 'some-key')) { ... }.Type Narrowing Behavior:
unknowntoUnknownRecord(=ReadonlyRecord<string, unknown>)null,undefined, primitives, and functionsUnknownRecord; admitting them at runtime would be inconsistent with the narrowed typetruefor every other non-null object, including dictionary objects created withObject.create(null)and instances such asDate,RegExp,Map,Set,Error, and user-defined classesWhy non-plain objects are included: since every property of
UnknownRecordis typedunknown, reading properties from any object through this narrowing is type-safe, andhasKey(backed byObject.hasOwn) answers own-property questions correctly on any object (e.g.Mapentries are not own properties, sohasKeycorrectly returnsfalsefor them). Restricting the guard to plain objects would require prototype checks that misjudge cross-realm objects and would prevent probing useful instances such asErrorsubclasses.Implementation:
isNonNullObject(u) && !Array.isArray(u).