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
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
}
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
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
Prefer JSR with Deno/Bun? Import TypeScript directly:
import { struct } from 'jsr:@nyaomaru/is-kit';
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)