npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

is-record

v0.1.1

Published

isRecord and 70+ more TypeScript type guards, assertions, and combinators that narrow unknown without casts. Tiny, zero-dependency, tree-shakable. Ships ESM + CJS + types; runs in browser, Node, Bun, and Deno.

Readme

is-record

isRecord and 70+ more TypeScript type guards.

A type guard is a function that checks a value's type at runtime and tells the compiler about it, so unknown becomes a real type with no casts. This package gives you isRecord — the guard this library is named after — plus a whole family of guards, assertions, and combinators for everything else.

Zero dependencies, fully tree-shakable, ships ESM + CJS + types, and runs anywhere ES2022 does — browser, Node, Bun, Deno.

npm types bundle license


Install

npm install is-record
pnpm add is-record
yarn add is-record
bun add is-record
import { isRecord } from 'is-record';

Deno (no install needed):

import { isRecord } from 'npm:is-record';

Why

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}

That four-liner gets re-written, re-tested, and re-shipped in countless codebases. This package is that guard done once, correctly — plus the whole family of guards you always end up reaching for next to it (primitives, numbers, strings, built-ins, JSON, combinators, assertions).

  • Zero dependencies. Nothing transitive, nothing to audit.
  • Tree-shakable. sideEffects: false + pure functions — your bundler keeps only the guards you import. Import one, ship one.
  • Universal. No node: imports; non-universal globals (Buffer, URL) are feature-detected, so the same build runs in browsers, Node, Bun, and Deno.
  • Type-safe. No any in the source; every guard returns a precise value is T predicate. The emitted .d.ts needs neither @types/node nor the DOM lib.

Quick start

import { isRecord, isString, isArrayOf, isOneOf, assertDefined } from 'is-record';

function handle(input: unknown) {
  if (!isRecord(input)) throw new TypeError('expected an object');
  // input is Record<string, unknown>

  if (isString(input.name)) {
    input.name.trim(); // string
  }

  if (isArrayOf(input.tags, isString)) {
    input.tags.join(', '); // string[]
  }

  if (isOneOf(input.method, ['GET', 'POST'] as const)) {
    input.method; // 'GET' | 'POST'
  }

  assertDefined(input.id, 'id is required');
  return input.id; // narrowed: not null | undefined
}

API

Every guard takes (value: unknown) and returns a type predicate unless noted.

Records & objects

| Guard | Narrows to | Notes | | --- | --- | --- | | isRecord | Record<string, unknown> | Non-null object that isn't an array. Accepts class instances & null-prototype objects. | | isObject | object | Any non-null object, including arrays. Excludes functions. | | isPlainObject | Record<string, unknown> | Strict: only {} literals / null-prototype. Rejects Date, Map, arrays, class instances. | | isEmptyObject | Record<string, never> | Empty record / array / Map / Set. | | hasOwn(value, key) | value & Record<K, unknown> | Type-safe own-property check. | | isKeyOf(object, key) | key is keyof T | Narrow a key to keyof an object. | | isInstanceOf(Ctor) | Guard<InstanceType<C>> | Builds an instanceof guard. | | isPropertyKey | PropertyKey | string \| number \| symbol. |

Primitives & nullish

| Guard | Narrows to | Notes | | --- | --- | --- | | isString | string | | | isNumber | number | Rejects NaN; accepts Infinity. | | isBoolean | boolean | | | isSymbol | symbol | | | isBigInt | bigint | | | isFunction | Function | Any callable. | | isNull / isUndefined | null / undefined | | | isNil | null \| undefined | | | isDefined | NonNullable<T> | Inverse of isNil; great as a .filter predicate. | | isPrimitive | string \| number \| boolean \| symbol \| bigint \| null \| undefined | | | isTruthy | NonNullable<T> | Filters out all falsy values at runtime. | | isFalsy | boolean | |

Numbers

| Guard | Narrows to | Notes | | --- | --- | --- | | isFiniteNumber | number | Rejects NaN, Infinity, -Infinity. | | isInteger | number | Number.isInteger. | | isSafeInteger | number | Number.isSafeInteger. | | isFloat | number | Finite, non-integer. | | isPositive / isNegative | number | > 0 / < 0. | | isNonNegative | number | >= 0. | | isInRange(value, min, max, inclusive?) | number | Inclusive by default. | | isNaNValue | boolean | True NaN check. |

Strings & validators

| Guard | Narrows to | Notes | | --- | --- | --- | | isNonEmptyString | string | Length > 0. | | isEmptyString | string | ''. | | isBlankString | string | Empty or whitespace-only. | | isNumericString | string | Parses as a finite number. | | isJsonString | string | Parses as JSON without throwing. | | isUuid | string | RFC 4122 shape (any version). | | isEmail | string | Pragmatic shape check. | | isUrl | string | Parses via the URL constructor. | | isBase64 | string | Valid standard Base64. |

Validators are pragmatic shape checks for guarding tool inputs and payloads — not RFC-exhaustive parsers for security-critical use.

Functions

| Guard | Narrows to | | --- | --- | | isAsyncFunction | (...args) => Promise<unknown> | | isGeneratorFunction | (...args) => Generator<unknown> | | isAsyncGeneratorFunction | (...args) => AsyncGenerator<unknown> | | isClass | new (...args) => unknown (class syntax) |

Built-ins

| Guard | Narrows to | Notes | | --- | --- | --- | | isDate / isValidDate | Date | isValidDate rejects Invalid Date. | | isRegExp | RegExp | | | isError | Error | Includes subclasses. | | isMap / isSet | Map / Set | Cross-realm safe. | | isWeakMap / isWeakSet | WeakMap / WeakSet | | | isPromise | Promise<T> | Native promises only. | | isPromiseLike | PromiseLike<T> | Any thenable. | | isArrayBuffer / isDataView | ArrayBuffer / DataView | | | isTypedArray | TypedArray | Any numeric typed-array view. | | isBuffer | Uint8Array | Node Buffer; false elsewhere (no @types/node needed). |

Arrays & iterables

| Guard | Narrows to | Notes | | --- | --- | --- | | isArray | unknown[] | Well-typed Array.isArray. | | isArrayOf(value, guard) | T[] | Array whose every element passes guard. | | isNonEmptyArray | [T, ...T[]] | | | isEmptyArray | [] | | | isIterable | Iterable<T> | Implements Symbol.iterator. | | isAsyncIterable | AsyncIterable<T> | Implements Symbol.asyncIterator. |

Emptiness

| Guard | Returns | Notes | | --- | --- | --- | | isEmpty | boolean | True for nil, '', [], {}, empty Map/Set. |

JSON

isJsonPrimitive, isJsonArray, isJsonObject, isJsonValue — recursively verify a value is JSON-safe (e.g. before JSON.stringify, or to validate a decoded payload). Exposed types: JsonValue, JsonObject, JsonArray, JsonPrimitive.

import { isJsonValue } from 'is-record';

isJsonValue({ a: [1, { b: 'c' }], d: null }); // true
isJsonValue({ fn: () => {} });                 // false

Combinators

Build new guards from existing ones — every combinator returns a reusable, tree-shakable predicate.

| Combinator | Result | Notes | | --- | --- | --- | | union(...guards) | Guard<A \| B \| …> | Passes if any guard passes. | | optional(guard) | Guard<T \| undefined> | | | nullable(guard) | Guard<T \| null> | | | not(guard) | (value) => boolean | Negation. | | isOneOf(value, options) | value is options[number] | Literal membership check. | | isRecordOf(valueGuard) | Guard<Record<string, T>> | Record with all-T values. |

import { union, optional, isRecordOf, isString, isNumber } from 'is-record';

const isId = union(isString, isNumber);     // Guard<string | number>
const isMaybeName = optional(isString);     // Guard<string | undefined>
const isStringMap = isRecordOf(isString);   // Guard<Record<string, string>>

Assertions

Throw on failure and narrow for the rest of the scope (TypeScript asserts).

| Assertion | Effect | | --- | --- | | assert(condition, message?) | Throws if falsy; narrows to truthy. | | assertDefined(value, message?) | Throws if nullish; narrows away null \| undefined. | | assertNever(value, message?) | Exhaustiveness guard for switch/default. |

import { assertNever } from 'is-record';

function area(shape: Circle | Square): number {
  switch (shape.kind) {
    case 'circle': return Math.PI * shape.r ** 2;
    case 'square': return shape.side ** 2;
    default: return assertNever(shape); // compile error if a case is added
  }
}

Utilities & types

  • toArray(value) — normalise a value-or-array (and nullish) into an array.
  • Exposed types: Guard<T>, GuardType<G>, NonEmptyArray<T>, plus the JSON and TypedArray types above.
import type { Guard } from 'is-record';

function parseList<T>(input: unknown, guard: Guard<T>): T[] {
  return Array.isArray(input) ? input.filter(guard) : [];
}

Compatibility & bundling

  • ESM & CommonJS via the exports map (import.mjs, require.js).
  • Types bundled (dist/index.d.ts) — no extra @types needed.
  • Tree-shaking: "sideEffects": false; importing one guard pulls in only that guard. With CJS (require), you get the whole module — use ESM for shaking.
  • Baseline: ES2022. Works in all current browsers, Node 18+, Bun, and Deno.

Contributing

See AGENTS.md for layout, conventions, and the "add a guard" checklist. In short:

bun install
bun run check      # biome lint + format (autofix)
bun run typecheck  # tsc strict
bun run test       # bun test
bun run build      # rollup → dist/

Changelog

See CHANGELOG.md.

License

MIT © Mohamed Meabed