A small, focused runtime type-checking library for TypeScript and JavaScript. Provides reliable type guards with accurate narrowing, predictable behavior, and consistent handling of edge cases.
This package helps you skip the repetitive work of writing runtime type checks. It gives you a consistent set of utilities, so you can focus on building instead of rewriting the same guards.
- Reliable Type Guards
Covers primitives, objects, arrays, functions, dates, errors, and more. - Accurate Type Narrowing
Uses proper TypeScript predicates (x is T) where runtime guarantees are valid. - Cross-Realm Safe Checks
Handles cases whereinstanceoffails (e.g.,iframes, multiple runtimes). - Consistent Runtime Semantics
Avoids misleading native behaviors (e.g.,Object.isSealed(null)). - Zero Dependencies
No external packages, suitable for production and libraries. - Well-Defined Behavior
Each function documents its guarantees and limitations explicitly. - Runtime Agnostic
Works in Node.js, browsers, Bun, and other modern JS environments.
JavaScript’s built-in type checks are inconsistent and sometimes misleading.
// Cross-realm issue
const ForeignError = window.frames[0].Error;
new ForeignError() instanceof Error; // false
// Primitive coercion (by spec, but often undesirable)
Object.isSealed(null); // true
Object.isFrozen(123); // trueThese results are technically correct by specification, but not useful for runtime validation.
import * as TG from 'tguard-js';
TG.isNull(null); // true
TG.isArray([]); // true
TG.isObject(null); // false
TG.isRecord({}); // true
TG.isRecord([]); // false
// Cross-realm safe
const ForeignError = window.frames[0].Error;
TG.isError(new ForeignError()); // true
// Predictable object checks
TG.isSealed(null); // false
TG.isFrozen(123); // falseThe library prioritizes predictability over spec quirks.
bun install tguard-jsnpm install tguard-jsimport { isString, isArrayOf, isRecord } from 'tguard-js';
// Basic validation
if (isString(value)) {
value.toUpperCase();
}
// Check if all array elements are string
if (isArrayOf(data, isString)) {
console.log(data[0]);
}
// Check if the config has `key` before consuming it
if (isRecord(config) && isString(config.key)) {
useConfig(config);
}Functions use x is T only when runtime checks guarantee it.
isString(x): x is string // safe
isArray(x): x is unknown[] // safe
isRecord(o): o is Record<PropertyKey, unknown> // safe
isEmptyArray(x): x is []
isEmptyObject(o): o is Record<PropertyKey, never>Generic predicates are only used when validated:
isArrayOf<T>(x, predicate): x is T[]
isRecordOf<T>(x, predicate): x is Record<string, T>This avoids unsafe narrowing.
| Function Type | Example |
|---|---|
| Type check | isDate |
| Validity check | isValidDate |
| Structure check | isPlainObject |
| Semantic check | isEmptyObject |
See APIs documentation:
→ API Overview
More patterns and examples:
→ Advanced Usage
bun run testor:
npm run testThe test suite covers:
- edge cases
- invalid inputs
- runtime consistency
Designed for minimal overhead:
- No allocations beyond necessary checks
- Direct use of native APIs
- Suitable for hot paths and validation layers
Fully compatible with TypeScript's strict mode:
if (isString(value)) {
value.charAt(0);
}Custom predicates:
function isStringOrBoolean(x: unknown): x is string | boolean {
return isString(x) || isBoolean(x);
}
isArrayOf(['a', true], isStringOrBoolean); // true- Node.js 14+ (with support both CommonJS and ESM)
- Modern browsers (ES2015+)
- Bun
- Deno
Contributions are welcome and appreciated. Please prefer small, focused changes with clear context and reasoning whenever possible.
Before opening a pull request, read the CONTRIBUTING.md guide for setup instructions, development workflow, and contribution guidelines.
© 2026 Ryuu Mitsuki. Licensed under the MIT License.
Made with ❤️ by developer, for developers.