Skip to content

Lightweight, zero-dependency toolkit for building `isFoo` style type guards in TypeScript. Runtime-safe πŸ›‘οΈ, composable 🧩, and ergonomic ✨. npm -> https://www.npmjs.com/package/is-kit

License

Notifications You must be signed in to change notification settings

nyaomaru/is-kit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

is-kit

is-kit logo

npm version JSR npm downloads License

Lightweight, zero-dependency toolkit for building isFoo style type guards in TypeScript. Runtime-safe πŸ›‘οΈ, composable 🧩, and ergonomic ✨.

πŸ“š full documentation

Why?

Tired of writing the same isFoo again and again? Let is-kit do it for you:

  • Less boilerplate
  • Type-safe
  • Composable
  • Zero-dependency

β˜• Grab a coffee, let is-kit do the boring work.

Install

Node via npm

pnpm add is-kit
# or
bun add is-kit
# or
npm i is-kit
# or
yarn add is-kit

ESM and CJS builds are provided for npm consumers. Types are bundled.

JSR (TypeScript source)

// Deno/Bun/JSR-aware tooling
import { define, and, or } from 'jsr:@nyaomaru/is-kit';

Quick start

Build is functions from tiny, composable pieces:

import {
  define,
  and,
  or,
  not,
  struct,
  oneOfValues,
  optional,
  isNumber,
  isString,
  predicateToRefine,
} from 'is-kit';

// Define small guards
const isShortString = define<string>((v) => isString(v) && v.length <= 3);
const isPositive = and(
  isNumber,
  predicateToRefine<number>((v) => v > 0)
);

// Combine them (or / not)
const isShortOrPositive = or(isShortString, isPositive);
const isOther = not(isShortOrPositive);

// Define object shapes
const isRole = oneOfValues(['admin', 'member'] as const);
const isUser = struct({
  id: isPositive, // number > 0
  name: isString, // string
  role: isRole, // 'admin' | 'member'
  nickname: optional(isShortString), // string <= 3 | undefined
});

// Use them
isPositive(3); // true
isShortOrPositive('foo'); // true
isShortOrPositive(false); // false
isOther('x'); // true

const maybeUser: unknown = { id: 7, name: 'Rin', role: 'admin' };
if (isUser(maybeUser)) {
  // The type is narrowed inside this block
  maybeUser.role; // 'admin' | 'member'
  maybeUser.nickname?.toUpperCase();
}

Composed guards stay reusable: isPositive can be used standalone or as part of a struct definition.

When validating complex shapes, reach for struct β€” and friends like arrayOf, recordOf, or oneOf.

Primitive guards

Built-in primitives: isString, isNumber (finite), isBoolean, isBigInt, isSymbol, isUndefined, isNull β€” and a preset isPrimitive for any primitive.

import { isPrimitive, isNumber } from 'is-kit';

isPrimitive('x'); // true
isPrimitive(123); // true
isPrimitive(NaN); // true (use isNumber for finite only)
isPrimitive({}); // false

Core Ideas

  • Define once: define<T>(fn) turns a plain function into a type guard.
  • Upgrade predicates: predicateToRefine(fn) adds narrowing.
  • Compose freely: and, or, not, oneOf, arrayOf, struct …
  • Stay ergonomic: helpers like nullable, optional, equals, safeParse, narrowKeyTo.

Key Narrowing

equalsBy preserves the base type and does not narrow selected fields to literals. When you need to narrow a property to a specific literal value, use narrowKeyTo.

import { narrowKeyTo, or, struct } from 'is-kit';

// Base guard (e.g., via struct)
type User = { id: string; age: number; role: 'admin' | 'guest' | 'trial' };
const isUser = struct({
  id: isString,
  age: isNumber,
  role: oneOfValues('admin', 'guest', 'trial'),
});

const byRole = narrowKeyTo(isUser, 'role');
const isGuest = byRole('guest'); // Readonly<User> & { role: 'guest' }
const isTrial = byRole('trial'); // Readonly<User> & { role: 'trial' }
const isGuestOrTrial = or(isGuest, isTrial);

declare const value: unknown;
if (isGuestOrTrial(value)) {
  // value.role is 'guest' | 'trial'
}

API Reference

For full API details and runnable examples, visit

πŸ“š See full document

Development

Requires Node 22 and pnpm 10.12.4 (via Corepack or mise). Want to hack on is-kit? See DEVELOPER.md for setup, scripts, and contribution workflow.

Contributing

See CONTRIBUTE.md for workflow, commit style, and tool setup. πŸš€

About

Lightweight, zero-dependency toolkit for building `isFoo` style type guards in TypeScript. Runtime-safe πŸ›‘οΈ, composable 🧩, and ergonomic ✨. npm -> https://www.npmjs.com/package/is-kit

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •