Yup, it's another type guard library. This one is designed with a focus on type-safety, portability, and performance, and is built to work on any modern ES2015+ runtime.
Note
Unless otherwise noted, all type guards are built to work in Deno, Node, Bun, Cloudflare Workers, and even in web browsers. If you find a type guard that doesn't work in a specific environment, please open an issue and I'll address it as soon as possible. Thanks!
This package is primarily distributed on JSR. If you're running Deno 2.x, it's built right in!
deno add jsr:@nick/isYou can also install @nick/is right into any Node codebase using the jsr
CLI, either via npx or an equivalent from your package manager of choice:
bunx jsr add @nick/isThe
--bunflag can be added to specifically instruct JSR to use Bun.
pnpm dlx jsr add @nick/isThe
--pnpmflag can be added to specifically instruct JSR to use PNPM.
yarn dlx jsr add @nick/isThe
--yarnflag can be added to specifically instruct JSR to use Yarn.
npx jsr add @nick/isThe recommended way to use the functions in this library is to import them on an as-needed basis, directly from their respective submodules.
See the API documentation for a complete list of available type guards.
import { isString } from "@nick/is/string";
import { isNumber } from "@nick/is/number";
import { isFiniteInteger } from "@nick/is/finite-integer";
// this is ^ also available via "@nick/is/finite/integer"The @nick/is project also exposes all of its type guards as named exports
from the root module, allowing you to import everything at once.
import { isNumber, isString } from "@nick/is";
console.assert(isString("@nick/is")); // OK
console.assert(isNumber(0)); // OKInstead of importing the default or namespace export, import only the functions you need:
import { isString } from "@nick/is";
console.assert(isString("@nick/is")); // OKOr for multiple functions:
import { isNumber } from "@nick/is";
console.assert(isNumber(0)); // OKOnce you've determined which type guards your codebase actually needs, it's recommended to migrate to named imports for production. This unlocks bundler tree-shaking, quicker build times, and a smaller final bundle size.
Checks if a given value is null.
import { isNull } from "@nick/is";
isNull(null); // true
isNull(undefined); // falseAliases:
is.nullJSR Documentation
Checks if a given value is undefined.
import { isUndefined } from "@nick/is";
isUndefined(undefined); // true
isUndefined(null); // falseAliases:
is.undefinedJSR Documentation
Checks if a given value is null or undefined.
import { isMissing } from "@nick/is";
isMissing(null); // true
isMissing(undefined); // true
isMissing(0); // falseAliases:
is.nullish/is.missingJSR Documentation
Checks if a given value is not undefined.
import { isDefined } from "@nick/is";
isDefined(0); // true
isDefined(undefined); // falseAliases:
is.definedJSR Documentation
Checks if a given value is a string.
import { isString } from "@nick/is";
isString("hello"); // true
isString(0); // falseAliases:
is.stringJSR Documentation
Checks if a given value is a number.
import { isNumber } from "@nick/is";
isNumber(0); // true
isNumber("hello"); // falseAliases:
is.numberJSR Documentation
Checks if a given value is a symbol.
import { isSymbol } from "@nick/is";
isSymbol(Symbol()); // true
isSymbol("hello"); // falseAliases:
is.symbolJSR Documentation
Checks if a given value is a bigint.
import { isBigInt } from "@nick/is";
isBigInt(BigInt(0)); // true
isBigInt(0); // falseAliases:
is.bigintJSR Documentation
Checks if a given value is a boolean.
import { isBoolean } from "@nick/is";
isBoolean(true); // true
isBoolean(0); // falseAliases:
is.booleanJSR Documentation
Checks if a given value is a valid property key, meaning it is either a string
or a symbol.
import { isPropertyKey } from "@nick/is;
isPropertyKey("hello"); // true
isPropertyKey(Symbol()); // true
isPropertyKey(0); // falseAliases:
is.propertyKeyJSR Documentation
Checks if a given value is a valid ECMAScript identifier, meaning it is a
string that is not a reserved word and is a valid identifier name.
import { isIdentifier } from "@nick/is";
isIdentifier("hello"); // true
isIdentifier("if"); // falseAliases:
is.identifierJSR Documentation
Checks if a given value is an object.
import { isObject } from "@nick/is";
isObject({}); // true
isObject([]); // true
isObject(() => {}); // false
isObject(null); // falseAliases:
is.objectJSR Documentati 868 on
Checks if a given value is a plain object, meaning it is an object that was
created with the Object constructor or a literal object.
import { isPlainObject } from "@nick/is";
isPlainObject({}); // true
isPlainObject(Object.create(null));
D62F
// true
isPlainObject(new Map()); // falseAliases:
is.plainObjectJSR Documentation
Checks if a given value is object-like, meaning it is not null and is not a
primitive value.
import { isObjectLike } from "@nick/is";
isObjectLike({}); // true
isObjectLike([]); // true
isObjectLike(() => {}); // true
isObjectLike(null); // falseAliases:
is.objectLikeJSR Documentation
Checks if a given value is a function.
import { isFunction } from "@nick/is";
isFunction(() => {}); // true
isFunction(0); // falseAliases:
is.functionJSR Documentation
Checks if a given value is a Promise object.
import { isPromise } from "@nick/is";
const promise = new Promise(() => {});
isPromise(promise); // true
isPromise(0); // falseAliases:
is.promiseJSR Documentation
Checks if a given value is a thenable, meaning it has a then method.
import { isPromiseLike } from "@nick/is";
const promise = { then() {} };
isPromiseLike(promise); // true
isPromiseLike(0); // falseAliases:
is.promiseLikeJSR Documentation
Checks if a given value is an array.
import { isArray } from "@nick/is";
isArray([]); // true
isArray({}); // falseAliases:
is.arrayJSR Documentation
Checks if a given value is array-like, meaning it has a length property and
its elements can be accessed using integer indices.
import { isArrayLike } from "@nick/is";
isArrayLike([]); // true
isArrayLike("hello"); // true
isArrayLike({}); // falseAliases:
is.arrayLikeJSR Documentation
Checks if a given value is an array-like object, meaning it is an object with a
length property and its elements can be accessed using integer indices.
import { isArrayLikeObject } from "@nick/is";
isArrayLikeObject([]); // true
isArrayLikeObject("hello"); // false
isArrayLikeObject({}); // falseAliases:
is.arrayLikeObjectJSR Documentation
Checks if a given value is a Map object. This is more reliable than the
instanceof Map method, as it will work across different realms and
environments, and it does not consider objects that were not created with
new Map() to be instances of a Map.
import { isMap } from "@nick/is";
const map = new Map();
isMap(map); // true
isMap({}); // falseAliases:
is.mapJSR Documentation
Checks if a given value is a Set object. This is more reliable than the
instanceof Set method, as it will work across different realms and
environments, and it does not consider objects that were not created with
new Set() to be instances of a Set.
import { isSet } from "@nick/is";
const set = new Set();
isSet(set); // true
isSet({}); // falseAliases:
is.setJSR Documentation
Checks if a given value is a WeakMap object. This is more reliable than the
instanceof WeakMap method, as it will work across different realms and
environments, and it does not consider objects that were not created with
new WeakMap() to be instances of a WeakMap.
import { isWeakMap } from "@nick/is";
const weakMap = new WeakMap();
isWeakMap(weakMap); // true
isWeakMap({}); // falseAliases:
is.weakMapJSR Documentation
Checks if a given value is a WeakSet object. This is more reliable than the
instanceof WeakSet method, as it will work across different realms and
environments, and it does not consider objects that were not created with
new WeakSet() to be instances of a WeakSet.
import { isWeakSet } from "@nick/is";
const weakSet = new WeakSet();
isWeakSet(weakSet); // true
isWeakSet({}); // falseAliases:
is.weakSetJSR Documentation
Checks if a given value is a WeakRef object. This is more reliable than the
instanceof WeakRef method, as it will work across different realms and
environments, and it does not consider objects that were not created with
new WeakRef() to be instances of a WeakRef.
import { isWeakRef } from "@nick/is";
const weakRef = new WeakRef({});
isWeakRef(weakRef); // true
isWeakRef({}); // falseAliases:
is.weakRefJSR Documentation
Checks if a given value is suitable for use as a key in a WeakMap or
WeakSet, or as a target value in a WeakRef.
import { isWeakKey } from "@nick/is";
isWeakKey({}); // true
isWeakKey(() => {}); // true
isWeakKey(Symbol()); // true
isWeakKey(0); // falseAliases:
is.weakKeyJSR Documentation
Checks if a given value is an iterable with a Symbol.iterator method.
import { isIterable } from "@nick/is";
isIterable([]); // true
isIterable("hello"); // true
isIterable(0); // falseAliases:
is.iterableJSR Documentation
Checks if a given value is an iterator, meaning it has a next method that
returns an object with value and done properties.
import { isIterator } from "@nick/is";
const iterator = [][Symbol.iterator]();
isIterator(iterator); // true
isIterator("hello"); // falseAliases:
is.iteratorJSR Documentation
Checks if a given value is an IterableIterator implementation, meaning it is
import { isIterableIterator } from "@nick/is";
const iterator = [][Symbol.iterator]();
const iterable = {
*[Symbol.iterator]() {
yield 1;
},
};
isIterableIterator(iterable); // false
isIterableIterator(iterable[Symbol.iterator]()); // true
isIterableIterator(iterator); // trueAliases:
is.iterableIteratorJSR Documentation
Checks if a given value is an async iterable object, meaning it has a
Symbol.asyncIterator method, and therefore is an implementation of the
AsyncIterable interface.
import { isAsyncIterable } from "@nick/is";
const posts = {
async *[Symbol.asyncIterator]() {
const posts = await fetch("https://jsonplaceholder.typicode.com/posts");
yield* await posts.json();
},
};
isAsyncIterable(posts); // true
const numbers = [1, 2, 3];
isAsyncIterable(numbers); // falseAliases:
is.asyncIterableJSR Documentation
Checks if a given value is an async iterator, meaning it has a next method
that returns a promise that resolves to an object with value and done
properties, implementing the AsyncIterator interface.
import { isAsyncIterator } from "@nick/is";
{
await using kv = await Deno.openKv();
const iter = kv.list({ prefix: [] });
if (isAsyncIterator(iter)) {
// this condition should always evaluate to true
let n = 0;
for await (const { key, value } of iter) {
if (n++ > 10) break; // limit to 10 items
console.log("key:", key, "\nvalue:", value, "\ncursor:", iter.cursor);
}
}
}Aliases:
is.asyncIteratorJSR Documentation
Checks if a value is an AsyncIterableIterator implementation, which is both an
async iterator with a next method that returns a promise, and also an
asynchronous iterable with a Symbol.asyncIterator method.
import { isAsyncIterableIterator } from "@nick/is";
const items = {
async *[Symbol.asyncIterator]() {
yield 1;
// simulate blocking I/O
await new Promise((resolve) => setTimeout(resolve, 1000));
yield 2;
},
};
isAsyncIterableIterator(items); // false
isAsyncIterableIterator(items[Symbol.asyncIterator]()); // trueAliases:
is.asyncIterableIteratorJSR Documentation
Checks if a given value is an array iterator, meaning it is an iterator object
that was created by calling the Symbol.iterator method on an array.
import { isArrayIterator } from "@nick/is";
const iterator = [][Symbol.iterator]();
isArrayIterator(iterator); // true
isArrayIterator("hello"); // falseAliases:
is.arrayIteratorJSR Documentation
Checks if a given value is a map iterator, meaning it is an iterator object that
was created by calling the entries, keys, or values method on a map.
import { isMapIterator } from "@nick/is";
const map = new Map();
const iterator = map.entries();
isMapIterator(iterator); // true
isMapIterator(map[Symbol.iterator]()); // true
isMapIterator("hello"[Symbol.iterator]()); // falseAliases:
is.mapIteratorJSR Documentation
Checks if a given value is a set iterator, meaning it is an iterator object that
was created by calling the entries, keys, or values method on a set.
import { isSetIterator } from "@nick/is";
const set = new Set();
const iterator = set.values();
isSetIterator(iterator); // true
isSetIterator(set[Symbol.iterator]()); // true
isSetIterator("hello"[Symbol.iterator]()); // falseAliases:
is.setIteratorJSR Documentation
Checks if a given value is a string iterator, meaning it is an iterator object
that was created by calling the Symbol.iterator method on a string.
import { isStringIterator } from "@nick/is";
const iterator = "hello"[Symbol.iterator]();
isStringIterator(iterator); // true
isStringIterator("hello"); // falseAliases:
is.stringIteratorJSR Documentation
Checks if a given value is an iterable object, meaning it is an object with a
Symbol.iterator method that returns an iterator.
import { isIterableObject } from "@nick/is";
const iterable = {
*[Symbol.iterator]() {
yield 1;
},
};
isIterableObject(iterable); // true
isIterableObject("hello"); // falseAliases:
is.iterableObjectJSR Documentation
Checks if a given value is a generator function, meaning it is a function that returns a generator object when called.
import { isGenerator } from "@nick/is";
const generator = function* () {
yield 1;
};
isGenerator(generator); // true
isGenerator("hello"); // falseAliases:
is.generatorJSR Documentation
Checks if a given value is a generator function, meaning it is a function that returns a generator object when called.
import { isGeneratorFunction } from "@nick/is";
const generator = function* () {
yield 1;
};
isGeneratorFunction(generator); // true
isGeneratorFunction("hello"); // falseAliases:
is.generatorFunctionJSR Documentation
Checks if a given value is an async generator function, meaning it is a function that returns an async generator object when called.
import { isAsyncGenerator } from "@nick/is";
const asyncGenerator = async function* () {
yield 1;
};
isAsyncGenerator(asyncGenerator); // true
isAsyncGenerator("hello"); // falseAliases:
is.asyncGeneratorJSR Documentation
Checks if a given value is an async generator function, meaning it is a function that returns an async generator object when called.
import { isAsyncGeneratorFunction } from "@nick/is";
const asyncGenerator = async function* () {
yield 1;
};
isAsyncGeneratorFunction(asyncGenerator); // true
isAsyncGeneratorFunction("hello"); // falseAliases:
is.asyncGeneratorFunctionJSR Documentation
Checks if a given value is a readable stream, meaning it is a valid
implementation of the ReadableStream interface.
import { isReadableStream } from "@nick/is";
const stream = new ReadableStream({ start() {} });
isReadableStream(stream); // true
isReadableStream("hello"); // falseAliases:
is.readableStreamJSR Documentation
Checks if a given value is a writable stream, meaning it is a valid
implementation of the WritableStream interface.
import { isWritableStream } from "@nick/is";
const stream = new WritableStream({ write() {} });
isWritableStream(stream); // true
isWritableStream("hello"); // falseAliases:
is.writableStreamJSR Documentation
Checks if a given value is a reader, meaning it is a valid implementation of the
Deno.Reader interface. This is not the same as the ReadableStream
interface's ReadableStreamDefaultReader type, which is a different kind of
reader.
import { isReader } from "@nick/is";
const reader = Deno.openSync("hello.txt");
isReader(reader); // true
isReader("hello"); // falseAliases:
is.readerJSR Documentation
Checks if a given value is a synchronous reader, meaning it is a valid
implementation of the ReaderSync interface.
import { isReaderSync } from "@nick/is";
const reader = Deno.openSync("hello.txt");
isReaderSync(reader); // trueAliases:
is.readerSyncJSR Documentation
Checks if a given value is a writer, meaning it is a valid implementation of the
Deno.Writer interface. This is not the same as the WritableStream
interface's WritableStreamDefaultWriter type, which is a different kind of
writer.
import { isWriter } from "@nick/is";
const writer = Deno.openSync("hello.txt");
isWriter(writer); // true
isWriter("hello"); // falseAliases:
is.writerJSR Documentation
Checks if a given value is a synchronous writer, meaning it is a valid
implementation of the WriterSync interface.
import { isWriterSync } from "@nick/is";
const writer = Deno.openSync("hello.txt");
isWriterSync(writer); // trueAliases:
is.writerSyncJSR Documentation
Checks if a given value is a closer, meaning it is a valid implementation of the
Deno.Closer interface.
import { isCloser } from "@nick/is";
const closer = Deno.openSync("hello.txt");
isCloser(closer); // true
isCloser("hello"); // falseAliases:
is.closerJSR Documentation
Checks if a given value is a template strings array, meaning it is an array of strings that were used as the first argument to a tagged template literal function.
import { isTemplateStringsArray } from "@nick/is";
function outdent(string: string): string;
function outdent(strings: TemplateStringsArray, ...args: unknown[]): string;
function outdent(input: string | TemplateStringsArray, ...args: unknown[]) {
if (isTemplateStringsArray(input)) {
input = String.raw(input, ...args);
}
// don't actually do it like this...
return input.replace(/^\n/, "").replace(/\n\s+/g, "\n");
}Aliases:
is.templateStringsArrayJSR Documentation
Checks if a given value is a BufferSource object, meaning it is either an
ArrayBuffer, SharedArrayBuffer, TypedArray, or a DataView.
import { isBufferSource } from "@nick/is";
const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);
const array = new Uint8Array(buffer);
isBufferSource(buffer); // true
isBufferSource(view); // true
isBufferSource(array); // true
isBufferSource({}); // falseAliases:
is.bufferSourceJSR Documentation
Checks if a given value is an ArrayBuffer object, which is a fixed-length
binary data buffer. This does not consider SharedArrayBuffer objects as
interchangeable with ArrayBuffer objects; to check for both types at once, use
the [isArrayBufferLike] type guard.
import { isArrayBuffer } from "@nick/is";
const buffer = new ArrayBuffer(8);
const shared = new SharedArrayBuffer(8);
isArrayBuffer(buffer); // true
isArrayBuffer(shared); // falseAliases:
is.arrayBufferJSR Documentation
Checks if a given value is a SharedArrayBuffer object, which is a fixed-length
binary data buffer that can be shared between multiple agents (such as workers).
import { isSharedArrayBuffer } from "@nick/is";
const buffer = new ArrayBuffer(8);
const shared = new SharedArrayBuffer(8);
isSharedArrayBuffer(buffer); // false
isSharedArrayBuffer(shared); // trueAliases:
is.sharedArrayBufferJSR Documentation
Checks if a given value is an ArrayBuffer or SharedArrayBuffer object.
import { isArrayBufferLike } from "@nick/is";
const buffer = new ArrayBuffer(8);
const shared
2D29
= new SharedArrayBuffer(8);
isArrayBufferLike(buffer); // true
isArrayBufferLike(shared); // trueAliases:
is.arrayBufferLikeJSR Documentation
Checks if a given value is an ArrayBufferView object, meaning it is either a
TypedArray or a DataView.
import { isArrayBufferView } from "@nick/is";
const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);
const array = new Uint8Array(buffer);
const object = {};
isArrayBufferView(object); // false
isArrayBufferView(buffer); // false
isArrayBufferView(view); // true
isArrayBufferView(array); // trueAliases:
is.arrayBufferViewJSR Documentation
Checks if a given value is a DataView object, which is a view of an
ArrayBuffer that allows reading and writing of the buffer's contents.
import { isDataView } from "@nick/is";
const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);
const object = {};
isDataView(object); // false
isDataView(buffer); // false
isDataView(view); // trueAliases:
is.dataViewJSR Documentation
Checks if a given value is a typed array, meaning it is an instance of one of
the TypedArray constructors, such as Int8Array, Uint8Array, etc.
import { isTypedArray } from "@nick/is";
const real = new Int8Array();
console.log("isTypedArray(real)", isTypedArray(real)); // true
const fake = Object.create(Int8Array.prototype);
console.log("isTypedArray(fake)", isTypedArray(fake)); // false
console.log("fake instanceof", fake instanceof Int8Array); // true (?!)Aliases DE97 :
is.typedArrayJSR Documentation
You can also use it to check for a specific typed array type by name:
import { isTypedArray } from "@nick/is";
const array = new Uint8Array();
console.assert(isTypedArray(array)); // OK
console.assert(isTypedArray(array, "Uint8Array")); // OK
console.assert(!isTypedArray(array, "Int8Array")); // invalid type
console.assert(!isTypedArray(array.buffer)); // ArrayBuffer != TypedArrayChecks if a given value is a Uint8Array object, which is a typed array of
8-bit unsigned integers.
import { isUint8Array } from "@nick/is";
const array = new Uint8Array();
console.assert(isUint8Array(array)); // true
console.assert(!isUint8Array(array.buffer)); // falseAliases:
is.uint8ArrayJSR Documentation
Checks if a given value is a Uint8ClampedArray object, which is a typed array
of 8-bit unsigned integers that are clamped to 0-255.
import { isUint8ClampedArray } from "@nick/is";
const array = new Uint8ClampedArray();
console.assert(isUint8ClampedArray(array)); // true
console.assert(!isUint8ClampedArray(array.buffer)); // falseAliases:
is.uint8ClampedArrayJSR Documentation
Checks if a given value is a Uint16Array object, which is a typed array of
16-bit unsigned integers.
import { isUint16Array } from "@nick/is";
const array = new Uint16Array();
console.assert(isUint16Array(array)); // true
console.assert(!isUint16Array(array.buffer)); // falseAliases:
is.uint16ArrayJSR Documentation
Checks if a given value is a Uint32Array object, which is a typed array of
32-bit unsigned integers.
import { isUint32Array } from "@nick/is";
const array = new Uint32Array();
console.assert(isUint32Array(array)); // true
console.assert(!isUint32Array(array.buffer)); // falseAliases:
is.uint32ArrayJSR Documentation
Checks if a given value is an Int8Array object, which is a typed array of
8-bit signed integers.
import { isInt8Array } from "@nick/is";
const array = new Int8Array();
console.assert(isInt8Array(array)); // true
console.assert(!isInt8Array(array.buffer)); // falseAliases:
is.int8ArrayJSR Documentation
Checks if a given value is an Int16Array object, which is a typed array of
16-bit signed integers.
import { isInt16Array } from "@nick/is";
const array = new Int16Array();
console.assert(isInt16Array(array)); // true
console.assert(!isInt16Array(array.buffer)); // falseAliases:
is.int16ArrayJSR Documentation
Checks if a given value is an Int32Array object, which is a typed array of
32-bit signed integers.
import { isInt32Array } from "@nick/is";
const array = new Int32Array();
console.assert(isInt32Array(array)); // true
console.assert(!isInt32Array(array.buffer)); // falseAliases:
is.int32ArrayJSR Documentation
Checks if a given value is a Float16Array object, which is a typed array of
16-bit half-precision floating point numbers.
import { isFloat16Array } from "@nick/is";
const array = new Float16Array();
console.assert(isFloat16Array(array)); // true
console.assert(!isFloat16Array(array.buffer)); // falseAliases:
is.float16ArrayJSR Documentation
Checks if a given value is a Float32Array object, which is a typed array of
32-bit single-precision floating point numbers.
import { isFloat32Array } from "@nick/is";
const array = new Float32Array();
console.assert(isFloat32Array(array)); // true
console.assert(!isFloat32Array(array.buffer)); // falseAliases:
is.float32ArrayJSR Documentation
Checks if a given value is a Float64Array object, which is a typed array of
64-bit double-precision floating point numbers.
import { isFloat64Array } from "@nick/is";
const array = new Float64Array();
console.assert(isFloat64Array(array)); // true
console.assert(!isFloat64Array(array.buffer)); // falseAliases:
is.float64ArrayJSR Documentation
Checks if a given value is a BigInt64Array object, which is a typed array of
64-bit signed integers (BigInts).
import { isBigInt64Array } from "@nick/is";
const array = new BigInt64Array();
console.assert(isBigInt64Array(array)); // true
console.assert(!isBigInt64Array(array.buffer)); // falseAliases:
is.bigInt64ArrayJSR Documentation
Contributing to the @nick/is project is warmly welcomed! If you've found a
bug, have an idea for a new feature, or have the time to fix or implement one of
the existing issues, please feel free to open a pull request. Before doing so, I
just ask that you take a moment to read through the contributing guidelines
and code of conduct to ensure your contributions align with the project's
values and goals.
If you plan on opening a pull request, please be sure to open an issue for it first, so that we can discuss the changes and have a place to track the progress towards merging them. This helps ensure you don't spend time working on something that's already being implemented (or, for example, left out of the project's scope or roadmap for some particular reason).