Skip to content

Latest commit

 

History

History
1046 lines (774 loc) · 33.8 KB

README.md

File metadata and controls

1046 lines (774 loc) · 33.8 KB

A set of JavaScript type checking helpers

Unfortunately, JavaScript does not provide convenient methods or helper functions to check a value's type. The mechanisms in place that could be a de facto way of doing it can have misleading results and are full of caveats to be aware of. Therefore having a set of type checking utility functions is left to userland implementations.

The functions provided by this library aims to type check values in a way I personally find intuitive and "caveat safe", coming from a PHP and Laravel set of type checking helpers.

Which means some functions may behave differently than that of other libraries like Lodash etc... .

Here's a quick example:

import is from '@vicgutt/isjs';
// or
import isArray from '@vicgutt/isjs/isArray';

is.array(123); // false
is.array([123]); // true
// or
isArray(123); // false
isArray([123]); // true

Installation

Install the package via NPM (or yarn):

npm i @vicgutt/isjs
yarn add @vicgutt/isjs

Then you may chose to import each individual functions separately (import isFoo from '@vicgutt/isjs/isFoo') or import an object containing all available functions (import is from '@vicgutt/isjs');

Note: This library is very "future facing" in the code that is distributed (dist folder), meaning it requires at least Node16+ and ES2020/ES2021 support from your JS compiler/bundler or browser.

Note bis: Check out the pro tips bellow.

Constants

A couple helper constants are provided by the library.

is.VERSION / VERSION

Retrieves the current library's version.

import is from '@vicgutt/isjs';
// or
import VERSION from '@vicgutt/isjs/constants/VERSION';

is.VERSION; // 'x.x.x'
// or
VERSION; // 'x.x.x'

is.SUPER_TYPES / SUPER_TYPES

Retrieves all "super types", that is, types that are composed of other smaller types.

Thoses types are:

  • nil (null & undefined)
  • number (int & float)
  • primitive (null, undefined, boolean, number, string, symbol, bigint)
  • derivative (anything that is not a primitive)
import is from '@vicgutt/isjs';
// or
import { SUPER_TYPES } from '@vicgutt/isjs/constants/TYPES';

is.SUPER_TYPES; // [...]
// or
SUPER_TYPES; // [...]

is.SUB_TYPES / SUB_TYPES

Retrieves all "sub types", that is, types that are NOT composed of other smaller types.

Thoses types are:

  • null
  • undefined
  • bool
  • nan
  • infinity
  • int
  • float
  • string
  • symbol
  • bigInt
  • array
  • object
  • function
import is from '@vicgutt/isjs';
// or
import { SUB_TYPES } from '@vicgutt/isjs/constants/TYPES';

is.SUB_TYPES; // [...]
// or
SUB_TYPES; // [...]

is.TYPES / TYPES

Retrieves all "types" (sub + super types).

import is from '@vicgutt/isjs';
// or
import TYPES from '@vicgutt/isjs/constants/TYPES';

is.TYPES; // [...]
// or
TYPES; // [...]

Available functions

is.array / isArray (Source | Tests)

Determines whether the given value is an array.

isArray(123); // false
isArray([123]); // true
isArray(Array(123)); // true
isArray(new Array(123)); // true

is.asyncFunction / isAsyncFunction (Source | Tests)

Determines whether the given value is an async function.

isAsyncFunction(123); // false
isAsyncFunction(new (class Hello {})()); // false
isAsyncFunction(() => {}); // false
isAsyncFunction(function () {}); // false
isAsyncFunction(function hello() {}); // false
isAsyncFunction(class Hello {}); // false
isAsyncFunction(new Function()); // false
isAsyncFunction(async function hello() {}); // true

is.bigInt / isBigInt (Source | Tests)

Determines whether the given value is a bigint.

isBigInt(123); // false
isBigInt(0n); // true
isBigInt(10n); // true
isBigInt(BigInt(10)); // true

is.blank / isBlank (Source | Tests)

Determines whether the given value is "blank".

A value is considered "blank" if:

  • The value is null or undefined
  • The value is NaN
  • The value has a "length" property and it's value, a number, is "falsy"
  • The value is a Map or a Set and it's size is "falsy"
  • The value, when a string, and trimmed, is empty (ex.: ' ')
  • The value, when an object, has no properties of it's own (ex.: !Object.keys(value).length)

A value is NOT considered "blank" if:

  • The value is numeric (ex.: 0, -0, '0', 3.72, '3.72')
  • The value is a boolean (ex.: false)
  • The value is a function
  • The value is a bigInt (ex.: 0n)
isBlank('   hey '); // false
isBlank(0); // false
isBlank(false); // false
isBlank(() => {}); // false
isBlank(document.querySelectorAll('body')); // false
isBlank('    '); // true
isBlank(NaN); // true
isBlank([]); // true
isBlank({}); // true
isBlank(Object.create({})); // true
isBlank(Object.create(null)); // true
isBlank(Object.assign([], { a: 1, b: 2 })); // true
isBlank(new Map()); // true
isBlank(new String()); // true
isBlank(document.querySelectorAll('no-existent-element')); // true

is.bool / isBool (Source | Tests)

This function is an alias of the isBoolean function.

isBool(1); // false
isBool(new Boolean(true)); // false
isBool(true); // true
isBool(false); // true
isBool(Boolean(true)); // true

isBool(1, true); // false
isBool(new Boolean(true), true); // true
isBool(true, true); // true
isBool(false, true); // true
isBool(Boolean(true), true); // true

is.boolean / isBoolean (Source | Tests)

Determines whether the given value is a boolean.

This function is able to differenciate between "boolean literals" and "boolean instances".

  • By "boolean literals" is meant booleans created using true or false.
  • By "boolean instances" is meant booleans created using the Boolean constructor (ex.: new Boolean(true))
isBoolean(1); // false
isBoolean(new Boolean(true)); // false
isBoolean(true); // true
isBoolean(false); // true
isBoolean(Boolean(true)); // true

isBoolean(1, true); // false
isBoolean(new Boolean(true), true); // true
isBoolean(true, true); // true
isBoolean(false, true); // true
isBoolean(Boolean(true), true); // true

is.class / isClass (Source | Tests)

Determines whether the given value is a class. This function is able to distinguish between a function and a class.

isClass(123); // false
isClass(() => {}); // false
isClass(function () {}); // false
isClass(function hello() {}); // false
isClass(new Function()); // false
isClass(new (class Hello {})()); // false
isClass(class Hello {}); // true

is.date / isDate (Source | Tests)

Determines whether the given value is a Date object.

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

is.defined / isDefined (Source | Tests)

Determines whether the given value is not undefined.

This function is the opposite of the isUndefined function.

isDefined(undefined); // false
isDefined(123); // true
isDefined(''); // true

is.derivative / isDerivative (Source | Tests)

Determines whether the given value is a "derivative".

A value is considered a "derivative" (a made up word by the way, suggestions welcomed) if it is NOT a primitive (null, undefined, boolean, number, string, symbol, bigint). Basically an Object in the general JavaScript sense of the word "object".

This function should behave exactly as Lodash' isObject function.

This function is an alias of the isNotPrimitive function.

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

is.documentFragment / isDocumentFragment (Source | Tests)

Determines whether the given value is a DocumentFragment.

isDocumentFragment({}); // false
isDocumentFragment(Document); // false
isDocumentFragment(Window); // false
isDocumentFragment(document.getRootNode()); // false
isDocumentFragment(document.body); // false
isDocumentFragment(document.querySelector('html')); // false
isDocumentFragment(document.createElement('img')); // false
isDocumentFragment(new DocumentFragment()); // true
isDocumentFragment(document.createDocumentFragment()); // true

is.element / isElement (Source | Tests)

Determines whether the given value is an Element.

Element is the most general base class from which all objects in a Document inherit. It only has methods and properties common to all kinds of elements. More specific classes inherit from Element.

isElement({}); // false
isElement(Document); // false
isElement(Window); // false
isElement(document.getRootNode()); // false
isElement(document.body); // true
isElement(document.querySelector('html')); // true
isElement(document.createElement('img')); // true

is.empty / isEmpty (Source | Tests)

Determines whether the given value is "empty".

A value is considered "empty" if:

  • The value is "falsy" (false, 0, -0, 0n, '', null, undefined, NaN)
  • The value has a "length" property and it's value, a number, is "falsy" (functions excluded)
  • The value is a Map or a Set and it's size is "falsy"
  • The value, when an object, has no properties of it's own (ex.: !Object.keys(value).length)
isEmpty('    '); // false
isEmpty(() => {}); // false
isEmpty(document.querySelectorAll('body')); // false
isEmpty(true); // false
isEmpty(false); // true
isEmpty(''); // true
isEmpty(0); // true
isEmpty([]); // true
isEmpty({}); // true
isEmpty(Object.create({})); // true
isEmpty(Object.create(null)); // true
isEmpty(Object.assign([], { a: 1, b: 2 })); // true
isEmpty(new Map()); // true
isEmpty(new String()); // true
isEmpty(document.querySelectorAll('non-existent-element')); // true

is.event / isEvent (Source | Tests)

Determines whether the given value is an event.

isEvent(new Event('yo')); // true
isEvent(new CustomEvent('yo')); // true

is.falsy / isFalsy (Source | Tests)

Determines whether the given value is "falsy".

A value is considered "falsy" if it is equal to one of the following:

  • false
  • 0
  • -0
  • 0n
  • ''
  • null
  • undefined
  • NaN

See:

isFalsy(1); // false
isFalsy(true); // false
isFalsy(0); // true
isFalsy(false); // true

is.filled / isFilled (Source | Tests)

Determines whether the given value is "filled".

A value is considered "filled" if:

  • The value is numeric (ex.: 0, -0, '0', 3.72, '3.72')
  • The value is a boolean (ex.: false)
  • The value is a function
  • The value is a bigInt (ex.: 0n)

A value is NOT considered "filled" if:

  • The value is null or undefined
  • The value is NaN
  • The value has a "length" property and it's value, a number, is "falsy"
  • The value has a "size" property and it's value, a number, is "falsy"
  • The value, when a string, and trimmed, is empty (ex.: ' ')
  • The value, when an object, has no properties of it's own (ex.: !Object.keys(value).length)

This function is the opposite of the isBlank function.

isFilled('    '); // false
isFilled(NaN); // false
isFilled([]); // false
isFilled({}); // false
isFilled(Object.create({})); // false
isFilled(Object.create(null)); // false
isFilled(Object.assign([], { a: 1, b: 2 })); // false
isFilled(new Map()); // false
isFilled(new String()); // false
isFilled(document.querySelectorAll('no-existent-element')); // false
isFilled('   hey '); // true
isFilled(0); // true
isFilled(false); // true
isFilled(() => {}); // true
isFilled(document.querySelectorAll('body')); // true

is.float / isFloat (Source | Tests)

Determines whether the given value is a float.

isFloat(123); // false
isFloat(123.0); // false
isFloat(123.123); // true

is.formData / isFormData (Source | Tests)

Determines whether the given value is a FormData object.

isFormData({}); // false
isFormData(new FormData()); // true

is.infinity / isInfinity (Source | Tests)

Determines whether the given value is Infinity.

isInfinity(Infinity); // true

is.int / isInt (Source | Tests)

This function is an alias of the isInteger function.

isInt(123.123); // false
isInt(123.0); // true
isInt(123); // true

is.integer / isInteger (Source | Tests)

Determines whether the given value is an integer.

isInteger(123.123); // false
isInteger(123.0); // true
isInteger(123); // true

is.iterable / isIterable (Source | Tests)

Determines whether the given value is an "iterable".

Iterable objects defines or customizes their iteration behavior, such as what values are looped over in a for...of construct. Some built-in types are built-in iterables with a default iteration behavior, such as Array or Map, while other types (such as Object) are not.

In order to be iterable, an object must implement the @@iterator method, meaning that the object (or one of the objects up its prototype chain) must have a property with an @@iterator key which is available via the constant Symbol.iterator (ex.: {[Symbol.iterator]: function() {}}).

See:

isIterable(123); // false
isIterable([]); // true
isIterable({ hey: 'hello', [Symbol.iterator]: function () {} }); // true

is.lengthy / isLengthy (Source | Tests)

Determines whether the given value is "lengthy".

A value is considered "lengthy" if it has a length property that returns a number.

isLengthy(123); // false
isLengthy({ length: '0' }); // false
isLengthy(''); // true
isLengthy([]); // true
isLengthy({ length: 0 }); // true

is.map / isMap (Source | Tests)

Determines whether the given value is a Map.

isMap([]); // false
isMap(new Map()); // true

is.nan / isNan (Source | Tests)

Determines whether the given value is NaN.

isNan(NaN); // true

is.nil / isNil (Source | Tests)

This function is an alias of the isNullOrUndefined function.

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

is.nodeList / isNodeList (Source | Tests)

Determines whether the given value is a NodeList.

isNodeList([]); // false
isNodeList(document.querySelectorAll('body')); // true

is.notEmpty / isNotEmpty (Source | Tests)

Determines whether the given value is not "empty".

A value is considered "empty" if:

  • The value is "falsy" (false, 0, -0, 0n, '', null, undefined, NaN)
  • The value has a "length" property and it's value, a number, is "falsy" (functions excluded)
  • The value has a "size" property and it's value, a number, is "falsy"
  • The value, when an object, has no properties of it's own (ex.: !Object.keys(value).length)

This function is the opposite of the isEmpty function.

isNotEmpty(false); // false
isNotEmpty(''); // false
isNotEmpty(0); // false
isNotEmpty([]); // false
isNotEmpty({}); // false
isNotEmpty(Object.create({})); // false
isNotEmpty(Object.create(null)); // false
isNotEmpty(Object.assign([], { a: 1, b: 2 })); // false
isNotEmpty(new Map()); // false
isNotEmpty(new String()); // false
isNotEmpty(document.querySelectorAll('non-existent-element')); // false
isNotEmpty('    '); // true
isNotEmpty(() => {}); // true
isNotEmpty(document.querySelectorAll('body')); // true
isNotEmpty(true); // true

is.notPrimitive / isNotPrimitive (Source | Tests)

Determines whether the given value is not a "primitive".

A value is considered a "primitive" if it is equal to one of the following:

  • null
  • undefined
  • boolean
  • number
  • string
  • symbol
  • bigint

See:

isNotPrimitive(String()); // false
isNotPrimitive(null); // false
isNotPrimitive(false); // false
isNotPrimitive(0n); // false
isNotPrimitive({}); // true
isNotPrimitive([]); // true
isNotPrimitive(new String()); // true

is.null / isNull (Source | Tests)

Determines whether the given value is null.

isNull(123); // false
isNull(''); // false
isNull(null); // true

is.nullOrUndefined / isNullOrUndefined (Source | Tests)

Determines whether the given value is null or undefined.

isNullOrUndefined(123); // false
isNullOrUndefined(null); // true
isNullOrUndefined(undefined); // true

is.number / isNumber (Source | Tests)

Determines whether the given value is a number. Including Infinity but excluding NaN.

This function is able to differenciate between "number literals" and "number instances".

  • By "number literals" is meant numbers created when writing a number directly, or with Number().
  • By "number instances" is meant numbers created using the Number constructor (ex.: new Number(123))
isNumber('hey'); // false
isNumber(new Number(123)); // false
isNumber(123); // true

isNumber('hey', true); // false
isNumber(new Number(123), true); // true
isNumber(123, true); // true

is.numeric / isNumeric (Source | Tests)

Determines whether the given value is a number or a "numeric string".

A string is considered numeric if it can be interpreted as / coerced to a number (as an integer or a float).

See:

isNumeric('11 23'); // false
isNumeric('hey'); // false
isNumeric(true); // false
isNumeric(1); // true
isNumeric(0); // true
isNumeric(11.23); // true
isNumeric('1'); // true
isNumeric('0'); // true
isNumeric('11.23'); // true

is.object / isObject (Source | Tests)

Determines whether the given value is an "object literal".

A value is considered an "object literal" if it is an object created by the Object constructor or one with a [[Prototype]] of null or one where it's prototype's constructor is Object.

This function is similair but NOT identical to Lodash's isPlainObject. The two functions differ in whether or not they choose to identify objects created using an existing object as their prototype instead of the base Object as "object literals" (ex.: const myObject = Object.create({})).

Lodash's isPlainObject doesn't, ours do, as long as the created object's prototype's constructor is Object (ex.: myObject.prototype.constructor === Object).

See:

isObject(''); // false
isObject([]); // false
isObject(Math); // false
isObject(Object); // false
isObject(class Yolo {}); // false
isObject(new (class Yolo {})()); // false
isObject({}); // true
isObject(new Object()); // true
isObject(Object.create({ a: 1, b: 2 })); // true (lodash.isPlainObject --> false)
isObject(Object.create(null)); // true

is.ofType / isOfType (Source | Tests)

Determines whether the given value is of the given type or one of the given types (if an array is given as a second argument).

Types can only be one of the following:

  • nil
  • number
  • primitive
  • derivative
  • null
  • undefined
  • bool
  • nan
  • infinity
  • int
  • float
  • string
  • symbol
  • bigInt
  • array
  • object
  • function
isOfType(null, 'undefined'); // false
isOfType(null, 'bool'); // false
isOfType(null, 'null'); // true
isOfType(null, 'nil'); // true

isOfType(null, ['undefined']); // false
isOfType(null, ['undefined', 'bool', 'array']); // false
isOfType(null, ['null', 'undefined', 'nil']); // true
isOfType(null, ['undefined', 'nil']); // true
isOfType(null, ['nil']); // true
isOfType(null, ['null']); // true
isOfType(null, ['primitive']); // true
isOfType(null, ['undefined', 'bool', 'array', 'primitive']); // true

is.primitive / isPrimitive (Source | Tests)

Determines whether the given value is a "primitive".

A value is considered a "primitive" if it is equal to one of the following:

  • null
  • undefined
  • boolean
  • number (including: number, NaN, Infinity)
  • string
  • symbol
  • bigint

See:

isPrimitive({}); // false
isPrimitive([]); // false
isPrimitive(new String()); // false
isPrimitive(String()); // true
isPrimitive(null); // true
isPrimitive(false); // true
isPrimitive(0n); // true

is.promise / isPromise (Source | Tests)

Determines whether the given value is a Promise.

isPromise([]); // false
isPromise(new Promise(() => {})); // true

is.set / isSet (Source | Tests)

Determines whether the given value is a Set.

isSet([]); // false
isSet(new Set()); // true

is.shadowRoot / isShadowRoot (Source | Tests)

Determines whether the given value is a ShadowRoot.

isShadowRoot({}); // false
isShadowRoot(Document); // false
isShadowRoot(Window); // false
isShadowRoot(document.getRootNode()); // false
isShadowRoot(document.body); // false
isShadowRoot(document.querySelector('html')); // false
isShadowRoot(document.createElement('img')); // false
isShadowRoot(document.createElement('span').attachShadow({ mode: 'open' })); // true

is.sizey / isSizey (Source | Tests)

Determines whether the given value is "sizey".

A value is considered "sizey" if it has a size property that returns a number.

isSizey(123); // false
isSizey({ size: '0' }); // false
isSizey(new Map()); // true
isSizey({ size: 0 }); // true

is.string / isString (Source | Tests)

Determines whether the given value is a string.

This function is able to differenciate between "string literals" and "string instances".

  • By "string literals" is meant strings created using '', "", ` `, or String().
  • By "string instances" is meant strings created using the String constructor (ex.: new String('hey'))
isString(1); // false
isString(new String('hey')); // false
isString('hey'); // true

isString(1, true); // false
isString(new String('hey'), true); // true
isString('hey', true); // true

is.symbol / isSymbol (Source | Tests)

Determines whether the given value is a Symbol.

isSymbol(123); // false
isSymbol(Symbol(123)); // true

is.syncFunction / isSyncFunction (Source | Tests)

Determines whether the given value is a sync function.

isSyncFunction(123); // false
isSyncFunction(new (class Hello {})()); // false
isSyncFunction(async function hello() {}); // false
isSyncFunction(() => {}); // true
isSyncFunction(function () {}); // true
isSyncFunction(function hello() {}); // true
isSyncFunction(class Hello {}); // true
isSyncFunction(new Function()); // true

is.textNode / isTextNode (Source | Tests)

Determines whether the given value is a Text.

isTextNode([]); // false
isTextNode(document.createTextNode('')); // true

is.truthy / isTruthy (Source | Tests)

Determines whether the given value is "truthy".

A value is considered "truthy" if it is NOT equal to one of the following:

  • false
  • 0
  • -0
  • 0n
  • ''
  • null
  • undefined
  • NaN

See:

isTruthy(0); // false
isTruthy(false); // false
isTruthy(1); // true
isTruthy(true); // true

is.typedAs / isTypedAs (Source | Tests)

Retrieves a given value's type.

The returned type can only be one of the following:

  • nil
  • bool
  • nan
  • infinity
  • int
  • float
  • string
  • symbol
  • bigInt
  • array
  • object
  • function
  • derivative
isTypedAs(null); // nil
isTypedAs(undefined); // nil
isTypedAs(true); // bool
isTypedAs(NaN); // nan
isTypedAs(Infinity); // infinity
isTypedAs(123); // int
isTypedAs(123.1); // float
isTypedAs(Symbol(123)); // symbol
isTypedAs(123n); // bigInt
isTypedAs([]); // array
isTypedAs(() => {}); // function
isTypedAs(class Hello {}); // function
isTypedAs(new Function()); // function
isTypedAs(Math); // derivative
isTypedAs(new Map()); // derivative
isTypedAs(new (class Hello {})()); // derivative

is.undefined / isUndefined (Source | Tests)

Determines whether the given value is undefined.

isUndefined(123); // false
isUndefined(''); // false
isUndefined(undefined); // true

is.urlSearchParams / isUrlSearchParams (Source | Tests)

Determines whether the given value is a URLSearchParams object.

isUrlSearchParams({}); // false
isUrlSearchParams(new URLSearchParams()); // true

is.weakMap / isWeakMap (Source | Tests)

Determines whether the given value is a WeakMap.

isWeakMap([]); // false
isWeakMap(new WeakMap()); // true

is.weakSet / isWeakSet (Source | Tests)

Determines whether the given value is a WeakSet.

isWeakSet([]); // false
isWeakSet(new WeakSet()); // true

Pro tips

Import what you need

For better tree shaking support and not having to import all the available functions when only a few is needed, I recommend creating and exporting a custom is object containing only the functions needed.

Something similar to:

// utils/is.js

import isString from '@vicgutt/isjs/isString';
import isClass from '@vicgutt/isjs/isClass';
import isFunction from '@vicgutt/isjs/isFunction';

export default {
    string: isString,
    class: isClass,
    function: isFunction,
};

// some-folder/some-file.js

import is from '../utils/is';

if (is.string(someVariable)) {
    //
}

Ensure TypeScript support

This library uses the newer Node's package.json's exports field to expose the individual functions to end users which may cause TypeScript not knowing where to get the associated .d.ts files. Therefore, if on a non compatible TypeScript version (which seems to be the case on the latest v4.5.5), I'd recomment adding the following key/values to your tsconfig.json.

{
    "baseUrl": ".",
    "paths": {
        "@vicgutt/isjs/*": ["./node_modules/@vicgutt/isjs/dist/*"]
    }
}

Contributing

If you're interested in contributing to the project, please read our contributing docs before submitting a pull request.

The "Available functions" portion of this README is generated by parsing each function's jsDoc.

License

The MIT License (MIT). Please see License File for more information.