DEV Community

Cover image for Build isXXX the Easy Way? Meet is-kit
nyaomaru
nyaomaru

Posted on

Build isXXX the Easy Way? Meet is-kit

Hey folks! The leaves are about to turn 🍁

I keep telling myself “just one more coffee”… but my hands are starting to shake ☕️😂
Anyway, I’m @nyaomaru, a frontend engineer.

 

Why I built this

If you write TypeScript a lot, you’ve probably hand-written type guards like value is Foo more times than you can count.
And keeping runtime checks perfectly aligned with types… kinda exhausting.

Enter is-kit — a lightweight, zero-dependency “guard generator kit” that slices through boring boilerplate ✂️

https://github.com/nyaomaru/is-kit

 

Why is-kit?

  • 🖋 Stop hand-writing value is Foo
    • Centralize guard definitions with define and predicateToRefine.
  • ⚙️ Compose logic with and / or / not
    • Express domain-specific conditions declaratively.
  • 🧩 Combinators like struct / array / tuple
    • Validate nested objects in just a few lines.
  • Runtime + type tests
    • Confidence via Jest (runtime) and tsd (type assertions).

 

How do I use it?

A super common case: “non-empty string” without hand-rolling the predicate signature.

import { define, isString } from 'is-kit';

const isNonEmptyString = define<string>(
  (value) => isString(value) && value.length > 0
);

isNonEmptyString('foo'); // true
isNonEmptyString(''); // false
Enter fullscreen mode Exit fullscreen mode

By passing the generic <string>, you don’t need to write the value is string predicate signature yourself — clean and tidy.

Another practical one: identifying a User shape.

import { struct, isString, isNumber, safeParseWith } from 'is-kit';

const isUser = struct({ id: isNumber, name: isString });

isUser({ id: 1, name: 'A' }); // true

const parseUser = safeParseWith(isUser);

const result = parseUser({ id: 'abc', age: 42 });
// result.valid === false

if (result.valid) {
  // on success
} else {
  // on failure
}
Enter fullscreen mode Exit fullscreen mode

You can check whether API responses or form inputs satisfy your expected types safely.

For more complex conditions, compose:

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

const isLongLiteral = predicateToRefine<string>((value) => value.length > 3);

const isLongString = and(isString, isLongLiteral);
isLongString('abcd'); // true
isLongString('ab'); // false
isLongString(123 as unknown); // false

or(isString, isNumber)('foo'); // true
not(isString)(123); // true
Enter fullscreen mode Exit fullscreen mode

With the combinators + primitives/object guards, you can express a wide range of isXXX guards cleanly.

 

Install & Ecosystem

Install from npm:

pnpm add is-kit
# or
bun add is-kit
# or
npm i is-kit
# or
yarn add is-kit
Enter fullscreen mode Exit fullscreen mode

Prefer JSR with Deno/Bun? Import TypeScript directly:

import { struct } from 'jsr:@nyaomaru/is-kit';
Enter fullscreen mode Exit fullscreen mode

 

Wrap-up

is-kit is a small kit for writing safe TypeScript guards:

  • Keep it tiny with define
  • Model bigger shapes with struct
  • Combine complicated logic with and / or / not
  • Make ergonomics nice with safeParse / safeParseWith

If you’re tired of drift between types and runtime checks, drop is-kit into your project and give it a spin. 🚀

https://github.com/nyaomaru/is-kit

And if you like it, a ⭐ would make my day! 😻

Top comments (0)