npm.io
3.0.1 • Published 1 year ago

utility-guards

Licence
MIT
Version
3.0.1
Deps
0
Size
88 kB
Vulns
0
Weekly
0

utility-guards

Set of guard function for runtime type checking in JavaScript with complete TypeScript support

npm package codecov package gzipped size



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
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