utility-guards
TypeScript icon, indicating that this package has built-in type declarations

3.0.0-rc1 • Public • Published

utility-guards

Utils for runtime and static type checking in JS and TS
All base type guards that you used to copy from project to project in one place

npm package codecov package gzipped size



Features:

  • 🛠️ Reliable type checking for JS runtime
  • 📦 Zero dependencies and only 1kb gzipped size
  • 📦 Tree-shaking friendly
  • 🔩 Full Typescript guard support
  • 🔩 Isomorphic: works in browser and node.js
  • 🔑 Addon: validate and validateStrict validators for runtime values (object) validation


API Reference




npm install utility-guards

Usage

// using named imports (tree-shaking friendly)
import { isString, isNumber, isNil, $not } from 'utility-guards';

isString('42'); // true
isNumber(42); // false

isString('42'); // true
isNumber(42); // false
$not(isNil)(0); // true
// using standalone imports (tree-shaking friendly)
import isString from 'utility-guards/isString';
import isNumber from 'utility-guards/isNumber';
import isNil from 'utility-guards/isNil';
import $not from 'utility-guards/not';

isString('42'); // true
isNumber(42); // false
$not(isNil)(0); // true
// Using default import – `is` namespace object
import is from 'utility-guards';

is.String('42'); // true
is.Number(42); // false
is.$not(is.Nil)(0); // true

API

isString(value)

Check if value is an string literal or string created by String constructor

isString('abc'); // true
isString(new String('abc')); // true
isString(42); // false

isNumber(value)

Check if value is an number literal or number created by Number constructor and not NaN

ℹ️ Although NaN is considered a number in JS, it's not a valid number in most cases you want to check if value is a valid number, so isNumber(NaN) returns false

isNumber(42); // true
isNumber(new Number(42)); // true
isNumber('42'); // false
isNumber(NaN); // false

isBigInt(value)

Check if value is an BigInt literal or BigInt created by BigInt constructor

isBigInt(42n); // true
isBigInt(BigInt(42)); // true
isBigInt(42); // false

isBoolean(value)

Check if value is an boolean

isBoolean(true); // true
isBoolean(false); // true
isBoolean(42); // false

isNaN(value)

Check if value is an NaN value.

ℹ️ This method is based on Number.isNaN and is not the same as global isNaN which converts value to number before checking

isNaN(NaN); // true
isNaN(2 + {}); // true
isNaN(42); // false
isNaN({}); // false

isUndefined(value)

Check if value is a undefined

isUndefined(undefined); // true
isUndefined(null); // false

isNull(value)

Check if value is a null

isNull(null); // true
isNull(undefined); // false

isNil(value)

Check if value is a null or undefined

isNil(null); // true
isNil(undefined); // true
isNil(0); // false

isPrimitive(value)

Check if value is a primitive

ℹ️ Primitive values in JS are: string, number, boolean, null, undefined, symbol, bigint

isPrimitive(42); // true
isPrimitive([1, 2, 3]); // false

isSymbol(value)

Check if value is a Symbol

isSymbol(Symbol('42')); // true
isSymbol('42'); // false

isRegExp(value)

Check if value is a RegExp object or RegExp literal

isRegExp(/\w+/); // true
isRegExp(new RegExp('\\w+')); // true

isError(value)

Check if value is an JS Error object

isError(new Error()); // true
isError(new TypeError()); // true

isAnyObject(value)

Check if value is a language type object (except null)

ℹ️ This method is not type safe and may lead to unexpected runtime errors. You probably want to use isPlainObject instead

isAnyObject({}); // true
isAnyObject([]); // true
isAnyObject(new Map()); // true
isAnyObject(new String()); // true

isPlainObject(value)

Check if value is a plain JavaScript object (excluding special classes or objects with other prototypes). It may be object literal {}, instance created by Object constructor or using Object.create(null | Object)

isPlainObject({}); // true
isPlainObject([]); // false
isPlainObject(new Map()); // false
isPlainObject(new String()); // false

isArray(value)

Check if value is array

isArray([]); // true
isArray({ 0: 'a', length: 10 }); // false

isFunction(value)

Check if value is an any function (except class definition)

isFunction(() => {}); // true
isFunction(function () {}); // true
isFunction(class {}); // false

isClass(value)

Check if value is a class definition

isClass(class {}); // true
isClass(() => {}); // false
isClass(function () {}); // false

isPromise(value)

Check if value is a native promise object

isPromise(Promise.resolve()); // true
isPromise(new Promise(() => {})); // true
isPromise({ then: () => {} }); // false

isPromiseLike(value)

Check if value is a promise-like object (has then method)

isPromiseLike(Promise.resolve()); // true
isPromiseLike(new Promise(() => {})); // true
isPromiseLike({ then: () => {} }); // true

isIterable(value)

Check if value is iterable (arrays, strings, maps, sets, etc.)

isIterable([]); // true
isIterable('42'); // true
isIterable(new Map()); // true

isDate(value)

Check if value is a valid JS Date object

isDate(new Date()); // true
isDate(new Date('Invalid Date')); // false

isHas(value, propertyName)

(value, propertyName) => boolean
(propertyName) => (value) => boolean

Check if value is an any object and has a direct property with given name

ℹ️ This method based on Object.prototype.hasOwnProperty and does not check prototype chain

isHas({ a: 42 }, 'a'); // true
isHas({ a: 42 }, 'b'); // false

isHasIn(value, propertyName)

(value, propertyName) => boolean
(propertyName) => (value) => boolean

Check if value is an any object and has a direct or inherited property with given name

ℹ️ This method based on in operator and checks prototype chain

isHasIn({ a: 42 }, 'a'); // true
isHasIn({ a: 42 }, 'b'); // false
isHasIn({ a: 42 }, 'toString'); // true

class A {
    method() {}
}

isHasIn(new A(), 'method'); // true

isArrayOf(value, guard)

(value, guard) => boolean
(guard) => (value) => boolean

Check if value is an array and all elements of the array match a given guard

isArrayOf([1, 2, 3], isNumber); // true
isArrayOf([1, 2, 3], isString); // false

isInstanceOf(value, constructor)

(value, constructor) => boolean
(constructor) => (value) => boolean

Check if value is instance of given constructor

ℹ️ This method based on instanceof operator

isInstanceOf(new Map(), Map); // true
isInstanceOf(new Map(), Set); // false

isEmpty(value)

Check if value is empty.

Value is considered as empty if it's:

  • Empty object: {}
  • Empty array: []
  • Empty Map: new Map()
  • Empty Set: new Set()
  • Empty string: ''
  • Nullable value: null or undefined
isEmpty({}); // true
isEmpty(new Set()); // true
isEmpty(null); // true
isEmpty(''); // true
isEmpty(0); // false

isFalsy(value)

Check if value is falsy

isFalsy(0); // true
isFalsy(''); // true
isFalsy(false); // true
isFalsy(null); // true
isFalsy(undefined); // true
isFalsy(NaN); // true
isFalsy(42); // false

isAny(value)

Returns true for any value. This is special case guard that originally was created to be used with validate function.

import validate from 'utility-guards/validate';

const schema = {
    a: isAny,
    b: isAny,
    c: isAny,
};

validate({ a: 42, b: '42', c: true }, schema); // true

is(value, expectedValue)

💡 You can use is container as a guard function

(value, expectedValue) => boolean
(value, expectedValue, isEqual) => boolean

(expectedValue) => (value) => boolean
(expectedValue, isEqual) => (value) => boolean

Check if value is equal to a given expected value.

ℹ️ By default will use Object.is for comparison, but you can pass custom isEqual function as a third argument

is(42, 42); // true

const isExactly42 = is(42);

isExactly42(42); // true
isExactly42('anything else'); // false
import is from 'utility-guards';
import isEqual from 'lodash/isEqual';

const isMyObject = is({ a: 3 }, isEqual);

isMyObject({ a: 3 }); // true
isMyObject({ a: 3, b: 4 }); // false

utility methods

All methods that starts with $ are utility methods for manipulating with guards

$not(guard)

Inverse given guard

const notIsNil = $not(isNil);

const arr = [1, null, 2, undefined, 3];
const filtered = arr.filter(notIsNil);

console.log(filtered); // [1, 2, 3] (type: number[])

$some(guard1, guard2, ...)

Combine multiple guards with some logic (logical OR)

const isNumberOrString = $some(isNumber, isString);

isNumberOrString(42); // true
isNumberOrString('42'); // true
isNumberOrString(true); // false

$every(guard1, guard2, ...)

Combine multiple guards with every logic (logical AND)

const isEmptyArray = $every(isArray, isEmpty);

isEmptyArray([]); // true
isEmptyArray([1, 2, 3]); // false

validate addon

(value, schema, options) => boolean
(schema, options) => (value) => boolean

Allows to validate runtime values (objects, arrays) with given schema or guard

Usage

Validate object with schema

import validate from 'utility-guards/validate';
import { isString, isNil, isBoolean } from 'utility-guards';

const obj = JSON.parse('...');

const schema = {
    a: isNumber,
    b: $some(isString, isNil), // string or nil
    c: {
        d: isBoolean,
        e: {
            f: isNumber,
            g: isString,
        },
    },
};

if (validate(obj, schema)) {
    // type of obj is inferred
    // { a: number, b: string | null, c: { d: boolean, e: { f: number, g: string } } }
    obj.c.e.f; // OK
} else {
    obj.c.e.f; // TS Error
}

Validate array with schema

import validate from 'utility-guards/validate';
import { isString, isNil, isBoolean, isArrayOf } from 'utility-guards';

const arr = JSON.parse('...');

const schema = [
    isString,
    isNil, // string or nil
    {
        d: isBoolean,
        e: isArrayOf(isNumber), // array of numbers only
    },
];

if (validate(arr, schema)) {
    // type of arr is inferred
    // [string, string | null, { d: boolean, e: number[] }]
    arr[2].e[0]; // OK
} else {
    arr[2].e[0]; // TS Error
}

Validate function args

One of the useful use-cases is to validate overloaded function arguments

import validate from 'utility-guards/validate';

type FunctionExample = {
    (value: string): void;
    (value: string, otherValue: number): void;
    (value: string, otherValue: number[]): void;
};

const example: FunctionExample = (...args: unknown[]) => {
    if (validate(args, [isString])) {
        const [value] = args; // [string]
    }
    if (validate(args, [isString, isNumber])) {
        const [value, otherValue] = args; // [string, number]
    }
    if (validate(args, [isString, isArrayOf(isNumber)])) {
        const [value, otherValue] = args; // [string, number[]]
    }

    // fallback
};

Validate value with guard

import validate from 'utility-guards/validate';
import { isArray, isEmpty, isString, isNil, isBoolean, $every, $some } from 'utility-guards';

const value = JSON.parse('...');

validate(value, isNumber); // is number
validate(value, $some(isNumber, isString)); // is number | string
validate(value, $every(isArray, isEmpty)); // is []

validate([1, 2, 3], isArrayOf(isNumber)); // true
validate([1, 2, 3, 'asd'], isArrayOf(isNumber)); // false

Allow extra properties

(value, schema) => boolean
(schema) => (value) => boolean

For objects and arrays, by default, validate method checks if value has all properties defined in schema. If you want to allow extra properties, you can pass allowExtra: true

import validate from 'utility-guards/validate';
import { isString, isNumber } from 'utility-guards';

const schema = {
    a: isNumber,
    b: isString,
};

// object
validate({ a: 42, b: '42', c: true }, schema); // false
validate({ a: 42, b: '42', c: true }, schema, { allowExtra: true }); // true

// array
validate([42, '42', true], [isNumber, isString]); // false
validate([42, '42', true], [isNumber, isString], { allowExtra: true }); // true



Compose and create custom guard

const isOkCode = $some(is(200), is(201), is(202));

const isUserProfile = validate({
    id: isNumber,
    name: isString,
    age: $some(isNumber, isNil),
    avatarUrl: $some(isString, isNil),
});

const isSuccessResult = validate({
    ok: is(true),
    code: isOkCode,
    result: {
        id: is.Number,
        users: is.ArrayOf(isUserProfile),
    },
});

// true
isSuccessResult({
    ok: true,
    code: 200,
    result: [
        {
            id: 42,
            user: {
                id: 42,
                name: 'John',
                age: null,
                avatarUrl: null,
            },
        },
    ],
});

Package Sidebar

Install

npm i utility-guards

Weekly Downloads

1

Version

3.0.0-rc1

License

MIT

Unpacked Size

123 kB

Total Files

136

Last publish

Collaborators

  • resetand