utility-guards
utility-guards
Set of guard function for runtime type checking in JavaScript with complete TypeScript support
Motivation
JavaScript has a notoriously inconsistent system for runtime type checking — with scattered use of typeof, instanceof, Array.isArray, Object.prototype.hasOwnProperty, and more.
As well, TypeScript does not work properly with all of these checks, leading to confusion and bugs.
This library was created to unify all these scattered patterns into a consistent, type-safe, and minimal API.
Features
- Simple runtime type checking
- Full TypeScript type inference support
- Tree-shaking friendly and zero dependencies
Installation
npm install utility-guards
Usage
import from the main package
import { isString, isNumber, isNil } from 'utility-guards';
isString(...);
isNumber(...);
isNil(...);
import from the sub-packages
import isString from 'utility-guards/isString';
import isNumber from 'utility-guards/isNumber';
import isNil from 'utility-guards/isNil';
isString(...);
isNumber(...);
isNil(...);
use is default export container
import is from 'utility-guards';
is.String(...)
is.Number(...)
is.Nil(...)
Table of Contents
API
Primitive Checks
isStringisNumberisFiniteNumberisBooleanisBigIntisSymbolisNullisUndefinedisNilisNaNisPrimitiveisFalsy
Object Checks
Function & Class Checks
Special Structures
Advanced Structural Guards
Combinators
Utility
API
Primitive Checks
isString
Checks if a value is a string (based on typeof)
isString('hello'); // true
isString(123); // false
isNumber
Checks if a value is a number (based on typeof)
isNumber(123); // true
isNumber('123'); // false
isFiniteNumber
Checks if a values is a finite number (not NaN, Infinity, or -Infinity)
isFiniteNumber(123); // true
isFiniteNumber(NaN); // false
isFiniteNumber(Infinity); // false
isFiniteNumber('42'); // false
isBoolean
Checks if a value is a boolean (based on typeof)
isBoolean(true); // true
isBoolean(0); // false
isBigInt
Checks if value is a bigint (based on typeof)
isBigInt(123n); // true
isBigInt(BigInt(123)); // true
isBigInt(123); // false
isSymbol
Checks for symbol type (based on typeof)
isSymbol(Symbol('foo')); // true
isNull
Checks if value is exactly null.
isNull(null); // true
isNull(undefined); // false
isUndefined
Checks if value is exactly undefined.
isUndefined(undefined); // true
isUndefined(null); // false
isNil
Checks if value is null or undefined.
isNil(null); // true
isNil(undefined); // true
isNaN
Strict NaN check
isNaN(NaN); // true
isNaN('foo'); // false
isPrimitive
Checks for JS primitive types including (string, number, boolean, bigint, symbol, null, and undefined).
isPrimitive('hello'); // true
isFalsy
Checks if value is falsy: false, 0, '', null, undefined
isFalsy(false); // true
isFalsy(0); // true
isFalsy(''); // true
Object Checks
isAnyObject
Loose check for object-like values (including arrays, maps).
isAnyObject({}); // true
isAnyObject([]); // true
isAnyObject(new Map()); // true
isAnyObject(new MyClass()); // true
isPlainObject
Strictly checks for plain objects with default prototype.
isPlainObject({}); // true
isPlainObject(new Map()); // false
isPlainObject(new MyClass()); // false
isPlainObject(Object.create(null)); // true
isEmpty
Checks if the value is empty (e.g. empty array, string, object, map, set).
isEmpty({}); // true
isEmpty([]); // true
isEmpty(''); // true
isEmpty(new Map()); // true
isEmpty(new Set()); // true
isArray
Checks if value is an array (based on Array.isArray)
isArray([]); // true
isArray({}); // false
isArrayOf
Checks if every item in an array passes a specified guard.
isArrayOf(['hello', 'world'], isString); // true
isArrayOf(['hello', 123], isString); // false
// can also use currying
is.ArrayOf(isString)(['hello', 'world']); // true
isTupleOf
Checks if the value is an array that exactly matches a given tuple schema.
isTupleOf(['hello', 123], [isString, isNumber]); // true
isTupleOf(['hello', 'world'], [isString, isNumber]); // false
isTupleOf([123], [isString, isNumber]); // false
isObjectOf
Checks if the value is an object that matches a given schema.
isObjectOf({ a: 1, b: 'hello' }, { a: isNumber, b: isString }); // true
isObjectOf({ a: 1, b: 'hello' }, { a: isNumber, b: isString, c: isBoolean }); // false
isObjectOf({ a: 1, b: 'hello', extra: true }, { a: isNumber, b: isString }); // true (see `isObjectExactOf` for strict check)
isObjectExactOf
Same as isObjectOf, but strictly checks that the object matches the schema without extra keys.
isObjectExactOf({ a: 1, b: 'hello', extra: true }, { a: isNumber, b: isString }); // false
Function & Class Checks
isFunction
Checks if a value is a function (but not a ES6 class constructor).
isFunction(() => {}); // true
isFunction(function () {}); // true
isFunction(class MyClass {}); // false
Although technically es6 classes are functions as well, it's can not be called like a regular function and in most majority of cases this is not the expected behavior. So this guard is designed to check for regular functions only
isClass
Checks if value is a ES6 class constructor. Uses Object.prototype.toString hack. Only works with ES6 classes defined with class keyword.
isClass(class MyClass {}); // true
isClass(function () {}); // false
Special Structures
isRegExp
Checks if value is a RegExp instance.
isRegExp(/abc/); // true
isRegExp(new RegExp('abc')); // true
isDate
Checks if value is a Date instance.
isDate(new Date()); // true
isDate(new Date('INVALID')); // true, includes invalid dates (see `isValidDate` for strict check)
isDate('2023-01-01'); // false
isValidDate
Same as isDate, but checks if the date is valid (i.e. not Invalid Date).
isValidDate(new Date()); // true
isValidDate(new Date('INVALID')); // false
isIterable
Checks if value is iterable, meaning it has a [Symbol.iterator] method and can be used in a for...of loop and spread operator.
isIterable(new Set([1, 2])); // true
isIterable(new Map()); // true
isIterable(new Map().keys()); // true
isIterable((function* () {})()); // true
isIterable({}); // false
isPromise
Checks if value is a native Promise instance.
isPromise(new Promise(() => {})); // true
isPromise({ then: () => {} }); // false
isPromiseLike
Checks if value is a promise-like object, meaning it has a then method.
isPromiseLike(new Promise(() => {})); // true
isPromiseLike({ then: () => {} }); // true
isPromiseLike({ then: 'foo' }); // false
isError
Checks if value is an instance of Error.
isError(new Error('foo')); // true
isError(new TypeError('foo')); // true
isError(new MyCustomError('foo')); // true
Advanced Structural Guards
isHasOwn
Checks if object has an own property (not inherited).
class Cls {
get key() {
return 'value';
}
}
const obj = { key: 'value' };
isHasOwn(obj, 'key'); // true
isHasOwn(new Cls(), 'key'); // false
isHasOwn('key')(obj); // support currying
isHasIn
Checks if property exists in object or its prototype chain.
isHasIn(obj, 'key'); // true
isHasIn(new Cls(), 'key'); // true
isHasIn('key')(obj); // support currying
isInstanceOf
Checks if value is instance of constructor using instanceof.
class A {}
class B extends A {}
isInstanceOf(new A(), A); // true
isInstanceOf(new B(), A); // true
isInstanceExactOf
Strict check that prototype is exactly the one from constructor (not a subclass).
isInstanceExactOf(new A(), A); // true
isInstanceExactOf(new B(), A); // false
Combinators
$not
Inverts a given guard
const isNotString = $not(isString);
isNotString(123); // true
$some
Logical OR combinator: passes if any guard returns true.
const isStringOrNumber = $some(isString, isNumber);
isStringOrNumber('hello'); // true
isStringOrNumber(123); // true
$every
Logical AND combinator: passes if all guards return true.
const isStringAndNotEmpty = $every(isString, $not(isEmpty));
isStringAndNotEmpty('hello'); // true
isStringAndNotEmpty(''); // false
Utility
is
Checks two values for equality using Object.is (or custom equality function).
Can be used for build more complex guards (e.g. isObjectOf, isTupleOf etc.).
is(123, 123); // true
is(123)(123); // support currying
isAny
A guard that always returns true. Useful as a wildcard in validations.
isAny(ANYTHING); // true
Types
All guards follow this signature:
// basic guards with single argument
(value: unknown) => value is T
// guards with multiple arguments (isArrayOf, isTupleOf, isObjectOf, isInstanceOf, isHasOwn etc.)
// supports currying
(value: unknown, ...args: unknown[]) => value is T
(...args: unknown[]) => (value: unknown) => value is T
License
MIT Resetand