utility-guards
v3.0.0-rc1
Published
Utils for runtime and static type checking in JS and TS
Downloads
38
Maintainers
Readme
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
andvalidateStrict
validators for runtime values (object) validation
API Reference
isString
isNumber
isBigInt
isBoolean
isNaN
isUndefined
isNull
isNil
isPrimitive
isSymbol
isRegExp
isError
isAnyObject
isPlainObject
isArray
isFunction
isClass
isPromise
isPromiseLike
isIterable
isDate
isHas
isHasIn
isArrayOf
isInstanceOf
isEmpty
isFalsy
isAny
is
$not
$some
$every
validate
validateStrict
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,
},
},
],
});