npm.io
1.7.0 • Published 1 month ago

@plq/is

Licence
MIT
Version
1.7.0
Deps
0
Size
99 kB
Vulns
0
Weekly
0

is

CI npm version

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.js import. 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 through require includes the whole library (~a few KB). Prefer import when 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, getTag and other tag-based checks rely on Object.prototype.toString, which can be spoofed via Symbol.toStringTag unless 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%.prototype Symbol.toStringTag getter), so they work across realms (e.g. node:vm contexts, iframes) and cannot be spoofed with Symbol.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 own Symbol.toStringTag has 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: isClass inspects 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/utils folder like is-object.ts
  • Write a function isObject in is-object.ts
  • Register it in src/index.ts: add import isObject from './utils/is-object.js' (the .js extension is required for the ESM build) and add isObject to the consolidated export { ... } block (do not use export { default as ... } from ... — it breaks Node ESM named imports, see the note at the top of src/index.ts)
  • Add new test to __tests__/type-matrix.test.ts file like describe('isObject', () => { tests('object', isObject) })
  • Run npm run lint
  • Run npm run test
  • Commit and push your changes
  • Create a pull request

Keywords