is
Small utility package that provides a set of functions to check if a given argument is of a certain type
Bundling and tree-shaking
The package ships two builds selected automatically via the exports map:
- ESM (
import { isString } from '@plq/is') — used by modern bundlers (webpack, Rollup, Vite, esbuild) and by Node.jsimport. Combined with"sideEffects": false, bundlers tree-shake it per function: importing a single check pulls in only that check and its direct dependencies (a one-import bundle is a few hundred bytes, not the whole library). - CommonJS (
require('@plq/is')) — the classic build. A CJS barrel cannot be reliably tree-shaken by bundlers, so bundling throughrequireincludes the whole library (~a few KB). Preferimportwhen bundle size matters.
Every function is small and self-contained; detect in particular depends only on getTag (about ten lines total) since v1.6.0.
Functions
detect
Returns the type of given value.
import { detect } from '@plq/is'
console.log(detect('')) // Output: 'string'
console.log(detect(1)) // Output: 'number'
console.log(detect(true)) // Output: 'boolean'
console.log(detect({})) // Output: 'object'
console.log(detect([])) // Output: 'array'
detect returns an all-lowercase type name derived from the value's tag: 'string', 'number', 'boolean', 'object', 'array', 'null', 'undefined', 'symbol', 'bigint', 'regexp', 'date', 'error', 'map', 'set', 'weakmap', 'weakset', 'promise', 'function', 'asyncfunction', 'generatorfunction', 'asyncgeneratorfunction', 'arraybuffer', 'dataview', 'int8array', 'uint8array', 'uint8clampedarray', 'int16array', 'uint16array', 'int32array', 'uint32array', 'float32array', 'float64array', 'bigint64array', 'biguint64array' and so on.
isArrayOf and isArrayOfSame use this vocabulary.
Note:
detect,getTagand other tag-based checks rely onObject.prototype.toString, which can be spoofed viaSymbol.toStringTagunless the check adds an extra guard.
getTag
Returns the tag of given value.
import { getTag } from '@plq/is'
console.log(getTag('')) // Output: '[object String]'
console.log(getTag(1)) // Output: '[object Number]'
console.log(getTag(true)) // Output: '[object Boolean]'
console.log(getTag({})) // Output: '[object Object]'
console.log(getTag([])) // Output: '[object Array]'
isFunction
Checks if a given value is a function.
import { isFunction } from '@plq/is'
console.log(isFunction(() => {})) // Output: true
console.log(isFunction({})) // Output: false
console.log(isFunction(async () => {})) // Output: false
isAsyncFunction
Checks if a given value is an asynchronous function.
import { isAsyncFunction } from '@plq/is'
console.log(isAsyncFunction(async () => {})) // Output: true
console.log(isAsyncFunction(async function* () {})) // Output: true
console.log(isAsyncFunction(() => {})) // Output: false
isGeneratorFunction
Checks if a given value is a generator function.
import { isGeneratorFunction } from '@plq/is'
console.log(isGeneratorFunction(function* () {})) // Output: true
console.log(isGeneratorFunction(async function* () {})) // Output: true
console.log(isGeneratorFunction(() => {})) // Output: false
isPromise
Checks if a given value is a Promise.
import { isPromise } from '@plq/is'
console.log(isPromise(Promise.resolve())) // Output: true
console.log(isPromise(async () => {})) // Output: false
isPromiseLike
Checks if a given value is a Promise-like.
import { isPromiseLike } from '@plq/is'
console.log(isPromiseLike(Promise.resolve())) // Output: true
console.log(isPromiseLike({ then: () => {} })) // Output: true
console.log(isPromiseLike(async () => {})) // Output: false
isArray
Checks if a given value is an array.
import { isArray } from '@plq/is'
console.log(isArray([])) // Output: true
console.log(isArray({})) // Output: false
isArrayOf
Checks if a given value is an array of a given type.
import { isArrayOf } from '@plq/is'
console.log(isArrayOf([], 'string')) // Output: false
console.log(isArrayOf(['a', 'b', 'c'], 'string')) // Output: true
console.log(isArrayOf(['a', 'b', 'c'], 'number')) // Output: false
console.log(isArrayOf(['a', 'b', 3], 'string')) // Output: false
The type argument is one of the all-lowercase type names returned by detect.
isArrayOfSame
Checks if a given array contains only elements of the same type.
Each element's type is determined with detect, so all elements must share the same detected type.
A non-array value or an empty array returns false.
import { isArrayOfSame } from '@plq/is'
console.log(isArrayOfSame([1, 2, 3])) // Output: true
console.log(isArrayOfSame([{}, {}])) // Output: true
console.log(isArrayOfSame([1, 'a'])) // Output: false
console.log(isArrayOfSame([() => {}, async () => {}])) // Output: false
console.log(isArrayOfSame([])) // Output: false
isObject
Checks if a given value is an object.
import { isObject } from '@plq/is'
console.log(isObject({})) // Output: true
console.log(isObject(() => {})) // Output: false
isObjectLike
Checks if a given value is an object-like.
import { isObjectLike } from '@plq/is'
console.log(isObjectLike({})) // Output: true
console.log(isObjectLike([])) // Output: true
console.log(isObjectLike(() => {})) // Output: false
isPlainObject
Checks if a given value is a plain object.
import { isPlainObject } from '@plq/is'
console.log(isPlainObject({})) // Output: true
console.log(isPlainObject(Object.create(null))) // Output: true
console.log(isPlainObject(() => {})) // Output: false
isNull
Checks if a given value is null.
import { isNull } from '@plq/is'
console.log(isNull(null)) // Output: true
console.log(isNull(undefined)) // Output: false
isUndefined
Checks if a given value is undefined.
import { isUndefined } from '@plq/is'
console.log(isUndefined(undefined)) // Output: true
console.log(isUndefined(null)) // Output: false
isString
Checks if a given value is a string.
import { isString } from '@plq/is'
console.log(isString('')) // Output: true
console.log(isString(1)) // Output: false
isNumber
Checks if a given value is a number.
import { isNumber } from '@plq/is'
console.log(isNumber(1)) // Output: true
console.log(isNumber(NaN)) // Output: true
console.log(isNumber('')) // Output: false
isNaN
Checks if a given value is NaN.
import { isNaN } from '@plq/is'
console.log(isNaN(NaN)) // Output: true
console.log(isNaN(1)) // Output: false
isBigint
Checks if a given value is a BigInt.
import { isBigint } from '@plq/is'
console.log(isBigint(BigInt(1))) // Output: true
console.log(isBigint(1)) // Output: false
isBoolean
Checks if a given value is a boolean.
import { isBoolean } from '@plq/is'
console.log(isBoolean(true)) // Output: true
console.log(isBoolean(false)) // Output: true
console.log(isBoolean(1)) // Output: false
isSymbol
Checks if a given value is a symbol.
import { isSymbol } from '@plq/is'
console.log(isSymbol(Symbol())) // Output: true
console.log(isSymbol(1)) // Output: false
isDate
Checks if a given value is a date.
import { isDate } from '@plq/is'
console.log(isDate(new Date())) // Output: true
console.log(isDate('2021-01-01')) // Output: false
isRegexp
Checks if a given value is a regular expression.
import { isRegexp } from '@plq/is'
console.log(isRegexp(/test/)) // Output: true
console.log(isRegexp('test')) // Output: false
isSet
Checks if a given value is a Set.
import { isSet } from '@plq/is'
console.log(isSet(new Set())) // Output: true
console.log(isSet([])) // Output: false
isMap
Checks if a given value is a Map.
import { isMap } from '@plq/is'
console.log(isMap(new Map())) // Output: true
console.log(isMap([])) // Output: false
isWeakset
Checks if a given value is a WeakSet.
import { isWeakset } from '@plq/is'
console.log(isWeakset(new WeakSet())) // Output: true
console.log(isWeakset([])) // Output: false
isWeakmap
Checks if a given value is a WeakMap.
import { isWeakmap } from '@plq/is'
console.log(isWeakmap(new WeakMap())) // Output: true
console.log(isWeakmap([])) // Output: false
isError
Checks if a given value is an error.
import { isError } from '@plq/is'
console.log(isError(new Error())) // Output: true
console.log(isError('Error')) // Output: false
isArraybuffer
Checks if a given value is an ArrayBuffer.
import { isArraybuffer } from '@plq/is'
console.log(isArraybuffer(new ArrayBuffer(1))) // Output: true
console.log(isArraybuffer(new Uint8Array(1))) // Output: false
isDataView
Checks if a given value is a DataView.
import { isDataView } from '@plq/is'
console.log(isDataView(new DataView(new ArrayBuffer(1)))) // Output: true
console.log(isDataView([])) // Output: false
isInt8array
Checks if a given value is an Int8Array.
import { isInt8array } from '@plq/is'
console.log(isInt8array(new Int8Array())) // Output: true
console.log(isInt8array(new Uint8Array())) // Output: false
isUint8array
Checks if a given value is a Uint8Array.
import { isUint8array } from '@plq/is'
console.log(isUint8array(new Uint8Array())) // Output: true
console.log(isUint8array(new Int8Array())) // Output: false
isUint8clampedarray
Checks if a given value is a Uint8ClampedArray.
import { isUint8clampedarray } from '@plq/is'
console.log(isUint8clampedarray(new Uint8ClampedArray())) // Output: true
console.log(isUint8clampedarray(new Uint8Array())) // Output: false
isInt16array
Checks if a given value is an Int16Array.
import { isInt16array } from '@plq/is'
console.log(isInt16array(new Int16Array())) // Output: true
console.log(isInt16array(new Uint16Array())) // Output: false
isUint16array
Checks if a given value is a Uint16Array.
import { isUint16array } from '@plq/is'
console.log(isUint16array(new Uint16Array())) // Output: true
console.log(isUint16array(new Int16Array())) // Output: false
isInt32array
Checks if a given value is an Int32Array.
import { isInt32array } from '@plq/is'
console.log(isInt32array(new Int32Array())) // Output: true
console.log(isInt32array(new Uint32Array())) // Output: false
isUint32array
Checks if a given value is a Uint32Array.
import { isUint32array } from '@plq/is'
console.log(isUint32array(new Uint32Array())) // Output: true
console.log(isUint32array(new Int32Array())) // Output: false
isFloat32array
Checks if a given value is a Float32Array.
import { isFloat32array } from '@plq/is'
console.log(isFloat32array(new Float32Array())) // Output: true
console.log(isFloat32array(new Float64Array())) // Output: false
isFloat64array
Checks if a given value is a Float64Array.
import { isFloat64array } from '@plq/is'
console.log(isFloat64array(new Float64Array())) // Output: true
console.log(isFloat64array(new Float32Array())) // Output: false
isBigint64array
Checks if a given value is a BigInt64Array.
import { isBigint64array } from '@plq/is'
console.log(isBigint64array(new BigInt64Array())) // Output: true
console.log(isBigint64array(new BigUint64Array())) // Output: false
isBiguint64array
Checks if a given value is a BigUint64Array.
import { isBiguint64array } from '@plq/is'
console.log(isBiguint64array(new BigUint64Array())) // Output: true
console.log(isBiguint64array(new BigInt64Array())) // Output: false
Note: the typed-array checks read the value's internal
[[TypedArrayName]]slot (via the%TypedArray%.prototypeSymbol.toStringTaggetter), so they work across realms (e.g.node:vmcontexts, iframes) and cannot be spoofed withSymbol.toStringTag: a non-typed-array claiming a typed-array tag is rejected, and a genuine typed array is still recognized by its own check even if its ownSymbol.toStringTaghas been tampered with.
isIterable
Checks if a given value is iterable.
import { isIterable } from '@plq/is'
console.log(isIterable([])) // Output: true
console.log(isIterable({})) // Output: false
isAsyncIterable
Checks if a given value is an async iterable.
import { isAsyncIterable } from '@plq/is'
console.log(isAsyncIterable((async function* () {})())) // Output: true
console.log(isAsyncIterable(async function* () {})) // Output: false
console.log(isAsyncIterable([])) // Output: false
Note: an async generator function itself is not async-iterable — the async generator object returned by calling it is.
isPrimitive
Checks if a given value is a primitive.
import { isPrimitive } from '@plq/is'
console.log(isPrimitive('')) // Output: true
console.log(isPrimitive(1)) // Output: true
console.log(isPrimitive(true)) // Output: true
console.log(isPrimitive(Symbol())) // Output: true
console.log(isPrimitive(null)) // Output: true
console.log(isPrimitive(undefined)) // Output: true
console.log(isPrimitive({})) // Output: false
console.log(isPrimitive([])) // Output: false
isEmpty
Checks if a given value is empty.
import { isEmpty } from '@plq/is'
console.log(isEmpty('')) // Output: true
console.log(isEmpty(0)) // Output: false
console.log(isEmpty(NaN)) // Output: true
console.log(isEmpty([])) // Output: true
console.log(isEmpty({})) // Output: true
console.log(isEmpty(new Set())) // Output: true
console.log(isEmpty(new Map())) // Output: true
console.log(isEmpty(() => {})) // Output: false
Note: numbers, booleans, WeakMap and WeakSet are never considered empty. NaN and whitespace-only strings count as empty.
isEmptyString
Checks if a given value is an empty string.
import { isEmptyString } from '@plq/is'
console.log(isEmptyString('')) // Output: true
console.log(isEmptyString(' ')) // Output: true
console.log(isEmptyString('test')) // Output: false
Note: the string is trimmed first, so whitespace-only strings are considered empty.
isEmptyArray
Checks if a given value is an empty array.
import { isEmptyArray } from '@plq/is'
console.log(isEmptyArray([])) // Output: true
console.log(isEmptyArray([1])) // Output: false
isEmptyObject
Checks if a given value is an empty object.
import { isEmptyObject } from '@plq/is'
console.log(isEmptyObject({})) // Output: true
console.log(isEmptyObject({ a: 1 })) // Output: false
isEmptySet
Checks if a given value is an empty Set.
import { isEmptySet } from '@plq/is'
console.log(isEmptySet(new Set())) // Output: true
console.log(isEmptySet(new Set([1]))) // Output: false
isEmptyMap
Checks if a given value is an empty Map.
import { isEmptyMap } from '@plq/is'
console.log(isEmptyMap(new Map())) // Output: true
console.log(isEmptyMap(new Map([['a', 1]]))) // Output: false
isClass
Checks if a given value is a class.
import { isClass } from '@plq/is'
class Test {}
console.log(isClass(Test)) // Output: true
console.log(isClass(new Test())) // Output: false
console.log(isClass(() => {})) // Output: false
Note:
isClassinspects the function's source text, so classes transpiled to plain functions (e.g. by TypeScript or Babel targeting ES5) are not detected.
isArguments
Checks if a given value is an arguments object.
import { isArguments } from '@plq/is'
const args = (function() {
return arguments
})()
console.log(isArguments(args)) // Output: true
console.log(isArguments([])) // Output: false
Development
Install dependencies
npm install
Lint
We use Biome to lint and format our code.
Check out biome.json
npm run lint
Run tests
We use Jest to test our code.
npm test
Build
We use TypeScript to build our code.
npm run build
Dev check list
- Add new file to
src/utilsfolder likeis-object.ts - Write a function
isObjectinis-object.ts - Register it in
src/index.ts: addimport isObject from './utils/is-object.js'(the.jsextension is required for the ESM build) and addisObjectto the consolidatedexport { ... }block (do not useexport { default as ... } from ...— it breaks Node ESM named imports, see the note at the top ofsrc/index.ts) - Add new test to
__tests__/type-matrix.test.tsfile likedescribe('isObject', () => { tests('object', isObject) }) - Run
npm run lint - Run
npm run test - Commit and push your changes
- Create a pull request