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

assertroute

v1.5.2

Published

Typescript fast & easy asserts

Downloads

131

Readme

assertroute

Tiny, fast runtime assertions with clean TypeScript narrowing — plus a block-scoped “route” wrapper that converts assertion failures into safe default returns.

Validate at the top; write clear, assumption-friendly logic in the middle. If any assert* throws an AssertError inside the route, we stop and return your default. Fewer try/catch, fewer defensive if checks, better narrowing.

Have you always disliked counting the brackets of your nested conditions? There has got to be a better way!

See also: CHEATSHEET.md for advanced patterns and quick references.

Install

npm i assertroute

Usage

After (assert-first, block-scoped route)

import { v } from 'assertroute';

const findClientTags = v.fn<string[]>([], (cdata: unknown, allclients: unknown[]) => {
  v.assertObject(cdata);
  v.assertArray(allclients);
  v.assertArray(cdata.tags, 'Expected tags array');
  v.assertArrayNotEmpty(cdata.tags, 'Tags must not be empty');

  const tags = cdata.tags as string[];
  v.assertArrayOnlyHasStrings(tags, 'Tags must be strings');

  // From here, TypeScript trusts the narrowing;
  // logic reads clearly with fewer conditionals.
  return allclients.filter((x) => Array.isArray(x.tagsShared) && x.tagsShared.some((t) => tags.includes(t))).map((x) => x.name);
});

Key benefits:

  • Strong narrowing: thrown AssertError prunes invalid paths, so TS treats code after asserts as safe.
  • Declarative checks: catalog of strict assert* helpers replaces scattered if guards.
  • Localized failure handling: one default return per route instead of many ad-hoc catch/fallbacks.

Dist files

  • dist/assertroute.esm.js – ESM build for modern bundlers/Node ESM (import).
  • dist/assertroute.cjs – CommonJS build for Node (require).
  • dist/assertroute.browser.min.js – IIFE build for browsers (window.assertroute = { … }).
  • *.map – Source maps for debugging.
  • assertroute.d.ts (+ .d.ts.map) – TypeScript typings (includes JSDoc).

package.json uses "exports" and "type": "module". Tree-shaking friendly ("sideEffects": false).

Core patterns

1) Throwing assertions (narrowing)

Plain function function toUpper(x: unknown) { assertString(x); return x.toUpperCase(); // x is string }

2) Route with fallback

const value = v.route(0, () => {
  v.assertNumber(Math.random());
  return 42;
}); // 42 or 0 on if assert failed with AssertError

3) Async route

const get = v.async(null, async () => {
  const r = await fetch('/data');
  v.assert(r.ok);
  return await r.json();
}); // Promise

4) Boolean validator for N asserts

import { v } from 'assertroute';
const isValidUser = v.confirmOne(() => {
  v.assertObject({ name: 'Luuk' });
  v.assertString('Luuk');
});
// true when single assertion passes

API index (kept)

All are function declarations (narrowing-safe). Names are stable; params are obvious from the name—see editor tooltips or the d.ts.

Routing

  • assertRoute, assertRouteAsync, routeWith, isValid

Core / Guards

  • assert, AssertError
  • assertString, assertNumber, assertBoolean, assertArray, assertObject, assertDate, assertFunction
  • assertPromiseLike, assertDefined, assertNonNull, assertPresent, assertInstanceOf

Expect (returns the narrowed value)

  • expectString, expectNumber, expectBoolean, expectArray, expectObject, expectDate

String

  • assertNonEmptyString
  • assertStringLength, assertStringLengthAtLeast, assertStringLengthAtMost, assertStringLengthBetween
  • assertStringContains, assertStringStartsWith, assertStringEndsWith, assertStringMatches
  • assertStringEqualsIgnoreCase
  • assertStringIncludesAny, assertStringIncludesAll
  • assertStringIsJSON, assertStringTrimmedNotEmpty
  • assertStringEqualsCanonical, assertStringContainsCanonical

Number

  • assertNumberGreaterThan, assertNumberGreaterOrEqual
  • assertNumberLessThan, assertNumberLessOrEqual
  • assertNumberBetween
  • assertNumberNotZero, assertNumberPositive, assertNumberNonNegative
  • assertNumberNegative, assertNumberNonPositive
  • assertNumberInteger, assertNumberSafeInteger
  • assertNumberApproxEquals
  • Aliases: assertIsNotZero, assertIsPositive, assertIsNegative

Array

  • assertArrayNotEmpty, assertArrayLength
  • assertArrayHasAnyOf, assertArrayHasEveryOf
  • assertArrayItemIsBoolean, assertArrayItemIsString, assertArrayItemIsNumber, assertArrayItemIsObject
  • assertArrayIncludesString, assertArrayIncludesNumber, assertArrayIncludesObject
  • assertArrayOnlyHasObjects, assertArrayOnlyHasStrings, assertArrayOnlyHasNumbers
  • assertArrayEveryIsFalsy, assertArrayEveryIsTruthy
  • assertArrayIncludesCondition
  • assertArrayUnique
  • Alias: assertIsArrayNotEmpty
  • Consistency (your addition): arrayIsConsistent (or assertArrayConsistent* if you used that naming)

Object / Keys

  • assertHasKey, assertHasKeys, assertKeyEquals, assertSameKeys
  • assertAllKeysFalsy, assertAllKeysSet, assertAnyKeyNull
  • assertNonEmptyRecord, assertSubset, assertHasPath

Map/Set

  • assertMapHasKey, assertSetHasValue

Dates

  • assertDateEarlier, assertDateLater, assertDateBetween, assertDateYear

Truthiness / Nullish

  • assertTrue, assertFalse, assertNull, assertUndefined

Equality

  • assertEquals, assertNotEquals, assertDeepEquals

Schema / Enums

  • assertMatchesSchema, assertOneOfPrimitive

DOM (safe outside browser via guards)

  • assertElement, assertElementHasChildren, assertElementHasChild
  • assertElementHasChildMatching, assertElementHasDescendant
  • assertElementHasAttribute, assertElementAttributeEquals
  • assertElementHidden, assertElementVisible

(If you kept the “extra” helpers)

  • assertPlainObject, assertNoExtraKeys
  • assertArrayOf, assertRecordOf, assertArrayUnique, assertArraySortedNumber
  • assertInstanceOfAny, assertURLString, assertUUID, assertEmail
  • assertNonEmptyMap, assertNonEmptySet
  • assertDeepSubset, assertDiscriminant, assertWithinSet
  • assertNever (exhaustiveness)

Notes

  • TypeScript: all functions are declared (not const) to avoid TS2775; narrowing works reliably.
  • Errors: assertions throw AssertError (not plain Error).
  • Tree-shaking: builds are side-effect free. Import only what you use.
  • Browser global: IIFE exposes window.assertroute with the full API.

Pro tip: keep one canonical name per helper. It improves discoverability, docs, and IntelliSense — no alias sprawl.

Happy asserting.

Route vs Fn

  • Fn: returns a wrapper function. Use when you want a reusable function that catches AssertError inside and returns a fallback. It never auto-executes.
  • Route: auto-executes when the callback has zero parameters; otherwise returns a wrapper. Use for concise “compute now or fall back” patterns.
  • With args: both return a wrapper — equivalent behavior. Prefer fn by default; use route only if you need its options.
  • Error handling: both catch AssertError. route/routeAsync also accept { catchNonAssertErrors?: boolean, onError?: (err: AssertError) => void }.

Examples

import * as v from 'assertroute';

// 1) Replace a function with a safe wrapper (fn)
export const getNonCheckedScenes = v.fn<string[]>([], () => {
  const rows = db.prepare('SELECT scene_id FROM scenes WHERE checkedForStamps = 0').all() as unknown[];
  const results = v.expectArrayNotEmpty(rows);
  v.assertObjectArrayEveryHasKeys(results, 'scene_id');
  return results.map((r) => (r as Record<string, unknown>).scene_id as string);
});

// 2) Compute immediately with auto-execute (route) — zero-arg callback runs now
export const bootScenes: string[] = v.route([], () => {
  const rows = db.prepare('SELECT scene_id FROM scenes WHERE boot = 1').all() as unknown[];
  const results = v.expectArray(rows);
  v.assertObjectArrayEveryHasKeys(results, 'scene_id');
  return results.map((r) => (r as Record<string, unknown>).scene_id as string);
});

// 3) With args, route returns a wrapper
export const scenesForProject = v.route<string[], [string]>([], (projectId) => {
  v.assertStringTrimmedNotEmpty(projectId);
  const rows = db.prepare('SELECT scene_id FROM scenes WHERE project_id = ?').all(projectId) as unknown[];
  const results = v.expectArray(rows);
  v.assertObjectArrayEveryHasKeys(results, 'scene_id');
  return results.map((r) => (r as Record<string, unknown>).scene_id as string);
});

// 4) Async variant
export const fetchJson = v.routeAsync<object | null, [string]>(
  null,
  async (url) => {
    v.assertString(url);
    const res = await fetch(url);
    v.assert(res.ok, 'Network failed');
    return await res.json();
  },
  { catchNonAssertErrors: true },
);