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

runtypex

v0.2.5

Published

Runtime type guards compiled from TypeScript types.

Downloads

1,003

Readme

runtypex

runtypex generates runtime validation and mapping code from TypeScript types. It keeps TypeScript types as the source of truth, so you do not need to maintain a separate schema just to validate data at runtime.

What It Solves

TypeScript types disappear after compilation. That means data from APIs, databases, files, or external modules can still be invalid at runtime even when the consuming code is type-safe at build time.

runtypex closes that gap by using the TypeScript compiler API to generate runtime guards and mappers during build.

Install

npm i runtypex

Quick Start

import { makeAssert, makeValidate } from "runtypex";

interface User {
  id: number;
  name: string;
  active: boolean;
}

const isUser = makeValidate<User>();
const assertUser = makeAssert<User>();

isUser({ id: 1, name: "Lux", active: true }); // true
assertUser({ id: "bad" }); // throws

Runtime vs Build-Time Behavior

makeValidate<T>() and makeAssert<T>() need the Vite plugin or TypeScript transformer to become real validation functions. makeMapper<TDto, TDomain>() also benefits from the transformer, but it still has a runtime fallback that can interpret the mapper spec directly.

| Execution path | makeValidate<T>() / makeAssert<T>() | makeMapper<TDto, TDomain>() | Docs generation | | --- | --- | --- | --- | | npm run dev with the Vite plugin | Works. Validation usually runs. | Works with validation. | Can generate when the dev server starts. | | npm run build with the Vite plugin | Works. | Works. | Generates docs. | | npm run build + NODE_ENV=production + removeInProd: true | Replaced with no-op validation. | Mapping still works; validation is removed. | Unaffected. | | No Vite plugin or transformer | Placeholder runtime fallback; does not inspect T. | Runtime fallback mapping still works. | Not generated. |

Vite Setup

// vite.config.ts
import { defineConfig } from "vite";
import { vitePlugin as runtypex } from "runtypex";

export default defineConfig({
  plugins: [runtypex()],
});

To replace validators with no-op functions in production builds:

export default defineConfig({
  plugins: [runtypex({ removeInProd: true })],
});

To generate mapper documentation by convention:

export default defineConfig({
  plugins: [
    runtypex({
      docs: {
        include: "src/features/**/*.mapper.ts",
      },
    }),
  ],
});

The docs generator finds defineMap<TDto, TDomainSource>()(...) calls under the included files, removes the Source suffix, and writes generated interfaces to runtypex.generated.ts next to the mapper file.

Feature Docs

| Feature | Description | | --- | --- | | Runtime validation | Generate makeValidate<T>() and makeAssert<T>() implementations from TypeScript types. | | Mapper | Convert DTO shapes into domain shapes with typed mapping specs. | | Mapping policy | Keep DTO path to domain field names consistent across multiple mappers. | | JSDoc generation | Generate field documentation from domain JSDoc and mapper metadata. | | Build integrations | Configure Vite, ts-loader, ESM exports, and build behavior. |

Mapper Example

import { defineMap, makeMapper, source, transform } from "runtypex/mapper";

interface UserDto {
  user_id: string;
  profile: { name: string };
  status: "ACTIVE" | "INACTIVE";
}

interface UserSource {
  /** User id */
  id: string;
  displayName: string;
  isActive: boolean;
}

const userMap = defineMap<UserDto, UserSource>()({
  id: source("user_id", {
    db: "users.user_id",
    dtoDescription: "User identifier from the user DTO.",
  }),
  displayName: source("profile.name"),
  isActive: transform("status", (value) => value === "ACTIVE"),
});

const toUser = makeMapper<UserDto, UserSource>(userMap);

Why runtypex?

| Goal | How runtypex handles it | | --- | --- | | Avoid schema duplication | Runtime code is generated from TypeScript types. | | Validate external data | Generated guards check values after compilation. | | Keep DTO and domain mapping explicit | Mapper specs make field movement visible and typed. | | Reduce runtime overhead | Build-time generation avoids dynamic schema parsing. |

Demo

runtypex-demo shows TypeScript types being transformed into runtime guards during build.