A comprehensive collection of performant type guards and assertions with excellent TypeScript support. This library serves as a drop-in replacement for Node.js's util/types module, while offering significantly better type inference, more extensive functionality, and cross-platform compatibility.
If you find @tool-belt/type-predicates helpful, please consider sponsoring the development:
Your support helps maintain and improve this library for the community! π
- π Better TypeScript Support: Advanced type inference with generics and precise type narrowing
- π¦ Zero Dependencies: Lightweight and self-contained
- π³ Tree-Shakeable: Full ESM support for optimal bundle sizes
- π Cross-Platform: Works in browsers, Node.js, and any JavaScript environment
- β Thorough Testing: Comprehensive test coverage for both runtime behavior and type safety
- π§ Extensive API: More comprehensive than Node.js built-in utilities
- π― Type Guards & Assertions: Every type check is available in both guard and assertion forms
npm install @tool-belt/type-predicates
pnpm add @tool-belt/type-predicates
yarn add @tool-belt/type-predicates
This library works in all modern browsers and Node.js environments. It's compiled to ES modules and CommonJS, with full support for tree-shaking to minimize bundle size.
// node:util/types import { isArray } from 'util/types'; const arr: unknown = ['a', 'b', 'c']; if (isArray(arr)) { // arr is typed as "unknown[]" - not very useful } // @tool-belt/type-predicates import { isArray } from '@tool-belt/type-predicates'; const arr: unknown = ['a', 'b', 'c']; if (isArray<string>(arr)) { // arr is typed as "string[]" - much better! }
import { assertIsString, assertIsArray } from '@tool-belt/type-predicates'; // Throws TypeError if not a string assertIsString(value); // After this line, TypeScript knows 'value' is a string // With custom error messages assertIsArray(data, { message: 'Configuration must be an array' }); // With nested validation assertIsArray<number>(data, { valueValidator: (item) => typeof item === 'number', message: 'Expected array of numbers', });
import { isUnion, isString, isNumber, createTypeGuard, } from '@tool-belt/type-predicates'; // Combine multiple type guards const isStringOrNumber = isUnion(isString, isNumber); // Create custom type guards const isPositiveNumber = createTypeGuard<number>( (value) => isNumber(value) && value > 0, );
Every guard returns a type predicate for TypeScript type narrowing:
import { isArray, isObject, isString, isNumber, isBoolean, isFunction, isPromise, isMap, isSet, isDate, isRegExp, isError, isNull, isUndefined, isNullish, isDefined, // ... and many more } from '@tool-belt/type-predicates'; // Use in conditionals if (isString(value)) { // TypeScript knows 'value' is a string here console.log(value.toUpperCase()); } // Use with array methods const strings = mixedArray.filter(isString); // strings is typed as string[]
Every guard has a corresponding assertion that throws on failure:
import { assertIsArray, assertIsObject, assertIsString, // ... all guards have assertion versions } from '@tool-belt/type-predicates'; function processConfig(config: unknown) { assertIsObject(config); // TypeScript now knows config is an object assertIsString(config.name, { message: 'Config name must be a string' }); // config.name is now typed as string }
import { isArray, isObject, isString } from '@tool-belt/type-predicates'; // Validate array elements const isStringArray = (value: unknown): value is string[] => isArray(value, { valueValidator: isString }); // Validate object values const isStringRecord = (value: unknown): value is Record<string, string> => isObject(value, { valueValidator: isString });
import { createTypeGuard, isUnion } from '@tool-belt/type-predicates'; // Create custom guards const isNonEmptyString = createTypeGuard<string>( (value) => isString(value) && value.length > 0, ); // Union types const isNumberOrString = isUnion(isNumber, isString);
isString/assertIsStringisNumber/assertIsNumberisBoolean/assertIsBooleanisBigInt/assertIsBigIntisSymbol/assertIsSymbolisUndefined/assertIsUndefinedisNull/assertIsNullisNullish/assertIsNullishisDefined/assertIsDefinedisNotNull/assertIsNotNullisNotNullish/assertIsNotNullish
isObject/assertIsObject- Checks if value is an object (not null)isPlainObject/assertIsPlainObject- Checks if value is a plain object (not a class instance)isRecord/assertIsRecord- Validates an object with specific key and value typesisEmptyObject/assertIsEmptyObject- Checks if object has no own propertiesisBoxedPrimitive/assertIsBoxedPrimitive- Checks if value is a boxed primitive
isArray/assertIsArray- Validates arrays with optional element type checkingisEmptyArray/assertIsEmptyArray- Checks if array has length of 0isNonEmptyArray/assertIsNonEmptyArray- Checks if array has length > 0isMap/assertIsMap- Validates Map objects with optional key/value type checkingisSet/assertIsSet- Validates Set objects with optional value type checkingisWeakMap/assertIsWeakMap- Checks if value is a WeakMapisWeakSet/assertIsWeakSet- Checks if value is a WeakSet
isFunction/assertIsFunction- Checks if value is a functionisAsyncFunction/assertIsAsyncFunction- Checks if value is an async functionisGeneratorFunction/assertIsGeneratorFunction- Checks if value is a generator functionisAsyncGeneratorFunction/assertIsAsyncGeneratorFunction- Checks if value is an async generator function
isIterable/assertIsIterable- Validates iterable objectsisIterator/assertIsIterator- Validates iterator objectsisGenerator/assertIsGenerator- Checks if value is a generatorisAsyncGenerator/assertIsAsyncGenerator- Checks if value is an async generatorisAsyncIterable/assertIsAsyncIterable- Validates async iterable objectsisMapIterator/assertIsMapIterator- Checks if value is a Map iteratorisSetIterator/assertIsSetIterator- Checks if value is a Set iterator
isError/assertIsError- Checks if value is an ErrorisNativeError/assertIsNativeError- Checks if value is a native Error type
isNaN/assertIsNaN- Checks if value is NaNisFinite/assertIsFinite- Checks if value is a finite numberisInteger/assertIsInteger- Checks if value is an integerisSafeInteger/assertIsSafeInteger- Checks if value is a safe integer
isEmptyString/assertIsEmptyString- Checks if string has length of 0isNonEmptyString/assertIsNonEmptyString- Checks if string has length > 0
isBuffer/assertIsBuffer- Checks if value is a BufferisArrayBuffer/assertIsArrayBuffer- Checks if value is an ArrayBufferisSharedArrayBuffer/assertIsSharedArrayBuffer- Checks if value is a SharedArrayBufferisAnyArrayBuffer/assertIsAnyArrayBuffer- Checks if value is any kind of ArrayBufferisArrayBufferView/assertIsArrayBufferView- Checks if value is an ArrayBufferViewisDataView/assertIsDataView- Checks if value is a DataViewisTypedArray/assertIsTypedArray- Checks if value is any TypedArray- Various specific TypedArray checkers (Int8Array, Uint8Array, etc.)
isDate/assertIsDate- Checks if value is a DateisRegExp/assertIsRegExp- Checks if value is a RegExpisPromise/assertIsPromise- Checks if value is a PromiseisArgumentsObject/assertIsArgumentsObject- Checks if value is an arguments object
You can create your own type guards using the createTypeGuard utility:
import { createTypeGuard, isNumber } from '@tool-belt/type-predicates'; // Create a type guard for positive numbers const isPositiveNumber = createTypeGuard<number>( (value) => isNumber(value) && value > 0, ); // Use it like any other guard if (isPositiveNumber(value)) { // TypeScript knows value is a number here // Runtime has verified value > 0 }
import { isError } from '@tool-belt/type-predicates'; try { // Your code that might throw } catch (error) { // TypeScript types catch blocks as 'unknown' if (isError(error)) { console.error(error.message); console.error(error.stack); } }
MIT