Comprehensive type checking functions providing TypeScript type guards for runtime type validation. Essential for type-safe JavaScript development and runtime type checking.
Functions for checking null and undefined values with strong TypeScript integration.
/**
* Checks if value is not null or undefined (primary type guard)
* @param x - Value to check
* @returns Type guard boolean indicating value is not null/undefined
*/
function isNotNil<T>(x: T | null | undefined): x is T;
/**
* Checks if value is null or undefined
* @param value - Value to check
* @returns Type guard boolean indicating value is null or undefined
*/
function isNil(value: unknown): value is null | undefined;
/**
* Checks if value is null
* @param value - Value to check
* @returns Type guard boolean indicating value is null
*/
function isNull(value: unknown): value is null;
/**
* Checks if value is undefined
* @param value - Value to check
* @returns Type guard boolean indicating value is undefined
*/
function isUndefined(value: unknown): value is undefined;Usage Examples:
import { isNotNil, isNil, isNull, isUndefined } from 'es-toolkit/predicate';
// Filter out null/undefined values with type safety
const mixedArray: (string | null | undefined)[] = [
'hello', null, 'world', undefined, 'example'
];
const validStrings = mixedArray.filter(isNotNil);
// TypeScript knows validStrings is string[] (not (string | null | undefined)[])
console.log(validStrings); // ['hello', 'world', 'example']
// Safe property access
function processUser(user: { name?: string; email?: string } | null) {
if (isNotNil(user)) {
// TypeScript knows user is not null here
console.log(`Processing user: ${user.name || 'Unknown'}`);
if (isNotNil(user.email)) {
// TypeScript knows user.email is string here
console.log(`Email: ${user.email.toLowerCase()}`);
}
}
}
// Validation and error handling
function validateInput(value: unknown): string {
if (isNil(value)) {
throw new Error('Input cannot be null or undefined');
}
if (typeof value !== 'string') {
throw new Error('Input must be a string');
}
return value; // TypeScript knows this is string
}
// Specific null/undefined checks
const data = { value: null, count: undefined, name: 'test' };
console.log(isNull(data.value)); // true
console.log(isUndefined(data.count)); // true
console.log(isNil(data.name)); // falseFunctions for checking primitive JavaScript types with TypeScript type narrowing.
/**
* Checks if value is boolean
* @param value - Value to check
* @returns Type guard boolean indicating value is boolean
*/
function isBoolean(value: unknown): value is boolean;
/**
* Checks if value is string
* @param value - Value to check
* @returns Type guard boolean indicating value is string
*/
function isString(value: unknown): value is string;
/**
* Checks if value is function
* @param value - Value to check
* @returns Type guard boolean indicating value is function
*/
function isFunction(value: unknown): value is (...args: any[]) => any;
/**
* Checks if value is symbol
* @param value - Value to check
* @returns Type guard boolean indicating value is symbol
*/
function isSymbol(value: unknown): value is symbol;
/**
* Checks if value is primitive (string, number, boolean, symbol, null, undefined)
* @param value - Value to check
* @returns Boolean indicating if value is primitive
*/
function isPrimitive(value: unknown): boolean;Usage Examples:
import { isBoolean, isString, isFunction, isSymbol, isPrimitive } from 'es-toolkit/predicate';
// Dynamic type checking with type safety
function processValue(value: unknown) {
if (isString(value)) {
// TypeScript knows value is string here
console.log(`String length: ${value.length}`);
return value.toUpperCase();
}
if (isBoolean(value)) {
// TypeScript knows value is boolean here
console.log(`Boolean value: ${value ? 'true' : 'false'}`);
return !value;
}
if (isFunction(value)) {
// TypeScript knows value is function here
console.log('Executing function...');
return value();
}
return value;
}
// Form validation
function validateFormField(field: unknown): string | null {
if (!isString(field)) {
return 'Field must be a string';
}
if (field.trim().length === 0) {
return 'Field cannot be empty';
}
return null; // Valid
}
// Event handler type checking
function addEventListener(element: Element, event: string, handler: unknown) {
if (!isFunction(handler)) {
throw new Error('Event handler must be a function');
}
element.addEventListener(event, handler);
}
// Symbol processing
const symbols = [Symbol('a'), 'string', Symbol('b'), 42];
const symbolsOnly = symbols.filter(isSymbol);
// TypeScript knows symbolsOnly is symbol[]
// Primitive vs object distinction
function serializeValue(value: unknown): string {
if (isPrimitive(value)) {
return String(value);
} else {
return JSON.stringify(value);
}
}Functions for checking various object types including built-in objects.
/**
* Checks if value is plain object (not array, function, Date, etc.)
* @param value - Value to check
* @returns Type guard boolean indicating value is plain object
*/
function isPlainObject(value: unknown): value is Record<PropertyKey, any>;
/**
* Checks if value is Date object
* @param value - Value to check
* @returns Type guard boolean indicating value is Date
*/
function isDate(value: unknown): value is Date;
/**
* Checks if value is RegExp object
* @param value - Value to check
* @returns Type guard boolean indicating value is RegExp
*/
function isRegExp(value: unknown): value is RegExp;
/**
* Checks if value is Error object
* @param value - Value to check
* @returns Type guard boolean indicating value is Error
*/
function isError(value: unknown): value is Error;Usage Examples:
import { isPlainObject, isDate, isRegExp, isError } from 'es-toolkit/predicate';
// Safe object property access
function mergeConfig(userConfig: unknown, defaultConfig: object) {
if (!isPlainObject(userConfig)) {
console.warn('User config is not a plain object, using defaults');
return defaultConfig;
}
// TypeScript knows userConfig is Record<PropertyKey, any> here
return { ...defaultConfig, ...userConfig };
}
// Date validation and formatting
function formatDate(value: unknown): string {
if (!isDate(value)) {
throw new Error('Expected Date object');
}
// TypeScript knows value is Date here
return value.toLocaleDateString();
}
// RegExp pattern validation
function validatePattern(pattern: unknown): RegExp {
if (isRegExp(pattern)) {
// TypeScript knows pattern is RegExp here
return pattern;
}
if (isString(pattern)) {
return new RegExp(pattern);
}
throw new Error('Pattern must be RegExp or string');
}
// Error handling and logging
function logError(error: unknown) {
if (isError(error)) {
// TypeScript knows error is Error here
console.error(`Error: ${error.message}`);
console.error(`Stack: ${error.stack}`);
} else {
console.error('Unknown error:', error);
}
}
// Data processing with type safety
function processApiResponse(response: unknown) {
if (!isPlainObject(response)) {
throw new Error('Invalid API response format');
}
// Now TypeScript knows response is an object
const { data, metadata } = response;
if (isDate(data?.timestamp)) {
console.log(`Last updated: ${data.timestamp.toISOString()}`);
}
return response;
}Functions for checking JavaScript collection types like Map, Set, and their weak variants.
/**
* Checks if value is Map
* @param value - Value to check
* @returns Type guard boolean indicating value is Map
*/
function isMap(value: unknown): value is Map<any, any>;
/**
* Checks if value is Set
* @param value - Value to check
* @returns Type guard boolean indicating value is Set
*/
function isSet(value: unknown): value is Set<any>;
/**
* Checks if value is WeakMap
* @param value - Value to check
* @returns Type guard boolean indicating value is WeakMap
*/
function isWeakMap(value: unknown): value is WeakMap<any, any>;
/**
* Checks if value is WeakSet
* @param value - Value to check
* @returns Type guard boolean indicating value is WeakSet
*/
function isWeakSet(value: unknown): value is WeakSet<any>;Usage Examples:
import { isMap, isSet, isWeakMap, isWeakSet } from 'es-toolkit/predicate';
// Collection serialization
function serializeCollection(collection: unknown): any {
if (isMap(collection)) {
// TypeScript knows collection is Map here
return {
type: 'Map',
entries: Array.from(collection.entries())
};
}
if (isSet(collection)) {
// TypeScript knows collection is Set here
return {
type: 'Set',
values: Array.from(collection.values())
};
}
return collection;
}
// Cache implementation detection
function getCacheSize(cache: unknown): number {
if (isMap(cache) || isSet(cache)) {
// TypeScript knows cache has .size property
return cache.size;
}
if (isWeakMap(cache) || isWeakSet(cache)) {
// Weak collections don't have size property
return -1; // Size unknown
}
return 0;
}
// Collection utilities
function clearCollection(collection: unknown): void {
if (isMap(collection) || isSet(collection)) {
collection.clear();
console.log('Collection cleared');
} else if (isWeakMap(collection) || isWeakSet(collection)) {
console.log('Cannot clear weak collection programmatically');
} else {
console.log('Not a collection type');
}
}
// Type-safe collection operations
function addToCollection<T>(collection: unknown, item: T): boolean {
if (isSet(collection)) {
collection.add(item);
return true;
}
if (isMap(collection) && typeof item === 'object' && item !== null) {
// Assume item has key-value structure for Map
const entries = Object.entries(item);
entries.forEach(([key, value]) => collection.set(key, value));
return true;
}
return false;
}Functions for checking array-like structures and binary data types.
/**
* Checks if value is ArrayBuffer
* @param value - Value to check
* @returns Type guard boolean indicating value is ArrayBuffer
*/
function isArrayBuffer(value: unknown): value is ArrayBuffer;
/**
* Checks if value is TypedArray (Int8Array, Uint8Array, etc.)
* @param value - Value to check
* @returns Type guard boolean indicating value is TypedArray
*/
function isTypedArray(value: unknown): value is TypedArray;
/**
* Checks if value is Buffer (Node.js Buffer)
* @param value - Value to check
* @returns Type guard boolean indicating value is Buffer
*/
function isBuffer(value: unknown): value is Buffer;
/**
* Checks if value is valid array-like length
* @param value - Value to check
* @returns Type guard boolean indicating value is valid length
*/
function isLength(value: unknown): value is number;Usage Examples:
import { isArrayBuffer, isTypedArray, isBuffer, isLength } from 'es-toolkit/predicate';
// Binary data processing
function processBinaryData(data: unknown): Uint8Array {
if (isArrayBuffer(data)) {
// TypeScript knows data is ArrayBuffer here
return new Uint8Array(data);
}
if (isTypedArray(data)) {
// TypeScript knows data is TypedArray here
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
}
if (isBuffer(data)) {
// TypeScript knows data is Buffer here (Node.js)
return new Uint8Array(data);
}
throw new Error('Expected binary data type');
}
// File handling in different environments
function getDataSize(data: unknown): number {
if (isArrayBuffer(data)) {
return data.byteLength;
}
if (isTypedArray(data)) {
return data.byteLength;
}
if (isBuffer(data)) {
return data.length;
}
return 0;
}
// Array-like validation
function createArrayLike(length: unknown, fillValue: any) {
if (!isLength(length)) {
throw new Error('Length must be a valid array length');
}
// TypeScript knows length is number here
return Array(length).fill(fillValue);
}
// Web API data conversion
function convertToBuffer(input: unknown): ArrayBuffer | null {
if (isArrayBuffer(input)) {
return input;
}
if (isTypedArray(input)) {
return input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength);
}
return null;
}Functions for checking browser-specific Web API types.
/**
* Checks if value is Blob
* @param value - Value to check
* @returns Type guard boolean indicating value is Blob
*/
function isBlob(value: unknown): value is Blob;
/**
* Checks if value is File
* @param value - Value to check
* @returns Type guard boolean indicating value is File
*/
function isFile(value: unknown): value is File;Usage Examples:
import { isBlob, isFile } from 'es-toolkit/predicate';
// File upload handling
function processUpload(fileData: unknown): Promise<string> {
if (isFile(fileData)) {
// TypeScript knows fileData is File here
console.log(`Processing file: ${fileData.name} (${fileData.size} bytes)`);
return fileData.text();
}
if (isBlob(fileData)) {
// TypeScript knows fileData is Blob here
console.log(`Processing blob: ${fileData.size} bytes, type: ${fileData.type}`);
return fileData.text();
}
throw new Error('Expected File or Blob');
}
// Drag and drop handling
function handleDrop(event: DragEvent) {
const items = event.dataTransfer?.items;
if (items) {
for (let i = 0; i < items.length; i++) {
const file = items[i].getAsFile();
if (isFile(file)) {
console.log(`Dropped file: ${file.name}`);
processUpload(file);
}
}
}
}
// Blob URL management
function createObjectURL(data: unknown): string | null {
if (isBlob(data) || isFile(data)) {
// TypeScript knows data is Blob or File here
return URL.createObjectURL(data);
}
return null;
}Functions for detecting the JavaScript execution environment.
/**
* Checks if running in browser environment
* @returns Boolean indicating if in browser
*/
function isBrowser(): boolean;
/**
* Checks if running in Node.js environment
* @returns Boolean indicating if in Node.js
*/
function isNode(): boolean;Usage Examples:
import { isBrowser, isNode } from 'es-toolkit/predicate';
// Environment-specific code
function getStorageAPI() {
if (isBrowser()) {
return {
get: (key: string) => localStorage.getItem(key),
set: (key: string, value: string) => localStorage.setItem(key, value),
remove: (key: string) => localStorage.removeItem(key)
};
}
if (isNode()) {
const fs = require('fs');
const path = require('path');
const storageFile = path.join(process.cwd(), 'storage.json');
return {
get: (key: string) => {
try {
const data = JSON.parse(fs.readFileSync(storageFile, 'utf8'));
return data[key] || null;
} catch {
return null;
}
},
set: (key: string, value: string) => {
let data = {};
try {
data = JSON.parse(fs.readFileSync(storageFile, 'utf8'));
} catch {}
data[key] = value;
fs.writeFileSync(storageFile, JSON.stringify(data));
},
remove: (key: string) => {
try {
const data = JSON.parse(fs.readFileSync(storageFile, 'utf8'));
delete data[key];
fs.writeFileSync(storageFile, JSON.stringify(data));
} catch {}
}
};
}
throw new Error('Unsupported environment');
}
// Polyfill loading
function loadPolyfills() {
if (isBrowser() && !window.fetch) {
// Load fetch polyfill for older browsers
console.log('Loading fetch polyfill...');
}
if (isNode() && !global.fetch) {
// Use node-fetch in Node.js environment
console.log('Setting up fetch for Node.js...');
}
}
// Logging configuration
function setupLogger() {
if (isBrowser()) {
return {
log: console.log,
error: console.error,
warn: console.warn
};
}
if (isNode()) {
const util = require('util');
return {
log: (msg: any) => process.stdout.write(util.format(msg) + '\n'),
error: (msg: any) => process.stderr.write(util.format(msg) + '\n'),
warn: (msg: any) => process.stderr.write('WARNING: ' + util.format(msg) + '\n')
};
}
return { log: () => {}, error: () => {}, warn: () => {} };
}Functions for checking asynchronous types and operations.
/**
* Checks if value is Promise
* @param value - Value to check
* @returns Type guard boolean indicating value is Promise
*/
function isPromise(value: unknown): value is Promise<any>;Usage Examples:
import { isPromise } from 'es-toolkit/predicate';
// Async/sync function handling
async function processResult<T>(result: T | Promise<T>): Promise<T> {
if (isPromise(result)) {
// TypeScript knows result is Promise<T> here
console.log('Awaiting promise...');
return await result;
}
// TypeScript knows result is T here
console.log('Using synchronous result');
return result;
}
// Function wrapper that handles both sync and async
function wrapFunction<T extends (...args: any[]) => any>(fn: T) {
return (...args: Parameters<T>): Promise<Awaited<ReturnType<T>>> => {
const result = fn(...args);
if (isPromise(result)) {
return result;
}
return Promise.resolve(result);
};
}
// Example usage
const syncFn = (x: number) => x * 2;
const asyncFn = async (x: number) => x * 2;
const wrappedSync = wrapFunction(syncFn);
const wrappedAsync = wrapFunction(asyncFn);
// Both return promises now
wrappedSync(5).then(console.log); // 10
wrappedAsync(5).then(console.log); // 10Functions for validating JSON-serializable data structures.
/**
* Checks if string is valid JSON
* @param value - String to check
* @returns Boolean indicating if string is valid JSON
*/
function isJSON(value: string): boolean;
/**
* Checks if value is JSON-serializable
* @param value - Value to check
* @returns Type guard boolean indicating value is JSON-serializable
*/
function isJSONValue(value: unknown): value is JSONValue;
/**
* Checks if value is JSON object
* @param value - Value to check
* @returns Type guard boolean indicating value is JSON object
*/
function isJSONObject(value: unknown): value is JSONObject;
/**
* Checks if value is JSON array
* @param value - Value to check
* @returns Type guard boolean indicating value is JSON array
*/
function isJSONArray(value: unknown): value is JSONArray;
type JSONValue = string | number | boolean | null | JSONObject | JSONArray;
type JSONObject = { [key: string]: JSONValue };
type JSONArray = JSONValue[];Usage Examples:
import { isJSON, isJSONValue, isJSONObject, isJSONArray } from 'es-toolkit/predicate';
// Safe JSON parsing
function safeParseJSON(text: string): any {
if (!isJSON(text)) {
throw new Error('Invalid JSON string');
}
return JSON.parse(text);
}
// API response validation
function validateApiResponse(response: unknown): JSONObject {
if (!isJSONObject(response)) {
throw new Error('API response must be a JSON object');
}
// TypeScript knows response is JSONObject here
return response;
}
// Data serialization safety
function safeStringify(data: unknown): string {
if (!isJSONValue(data)) {
throw new Error('Data is not JSON-serializable');
}
// TypeScript knows data is JSON-serializable here
return JSON.stringify(data);
}
// Array processing
function processJSONArray(data: unknown): any[] {
if (!isJSONArray(data)) {
throw new Error('Expected JSON array');
}
// TypeScript knows data is JSONArray here
return data.map(item => {
if (isJSONObject(item)) {
return { ...item, processed: true };
}
return item;
});
}
// Configuration validation
function validateConfig(config: unknown) {
if (isJSONObject(config)) {
// Validate required properties
const { database, server } = config;
if (isJSONObject(database) && isJSONObject(server)) {
return { database, server };
}
}
throw new Error('Invalid configuration format');
}Functions for deep equality checking with customization options.
/**
* Performs deep equality check
* @param a - First value to compare
* @param b - Second value to compare
* @returns Boolean indicating if values are deeply equal
*/
function isEqual(a: any, b: any): boolean;
/**
* Deep equality check with custom comparator
* @param a - First value to compare
* @param b - Second value to compare
* @param customizer - Optional custom comparison function
* @returns Boolean indicating if values are deeply equal
*/
function isEqualWith(
a: any,
b: any,
customizer?: (a: any, b: any) => boolean | undefined
): boolean;Usage Examples:
import { isEqual, isEqualWith } from 'es-toolkit/predicate';
// Deep object comparison
const obj1 = {
user: { name: 'Alice', age: 30 },
settings: { theme: 'dark', notifications: true }
};
const obj2 = {
user: { name: 'Alice', age: 30 },
settings: { theme: 'dark', notifications: true }
};
const obj3 = {
user: { name: 'Alice', age: 31 },
settings: { theme: 'dark', notifications: true }
};
console.log(isEqual(obj1, obj2)); // true
console.log(isEqual(obj1, obj3)); // false
// Array comparison
const arr1 = [1, [2, 3], { a: 4 }];
const arr2 = [1, [2, 3], { a: 4 }];
console.log(isEqual(arr1, arr2)); // true
// Custom equality with tolerance
function approximateEqual(a: any, b: any): boolean | undefined {
if (typeof a === 'number' && typeof b === 'number') {
return Math.abs(a - b) < 0.001;
}
return undefined; // Use default comparison
}
const point1 = { x: 1.0001, y: 2.0002 };
const point2 = { x: 1.0000, y: 2.0000 };
console.log(isEqual(point1, point2)); // false
console.log(isEqualWith(point1, point2, approximateEqual)); // true
// Date comparison with custom handling
function dateEqual(a: any, b: any): boolean | undefined {
if (isDate(a) && isDate(b)) {
return a.getTime() === b.getTime();
}
return undefined;
}
const date1 = new Date('2024-01-01');
const date2 = new Date('2024-01-01');
console.log(isEqualWith({ created: date1 }, { created: date2 }, dateEqual)); // trueimport { isNotNil, isString, isPlainObject } from 'es-toolkit/predicate';
function processUserData(data: unknown) {
if (isNotNil(data) && isPlainObject(data)) {
const { name, email } = data;
if (isString(name) && isString(email)) {
return { name: name.trim(), email: email.toLowerCase() };
}
}
throw new Error('Invalid user data');
}import { isNotNil, isString, isFunction } from 'es-toolkit/predicate';
const mixedArray: unknown[] = [
'hello', null, () => 'function', undefined, 'world', 42
];
const strings = mixedArray.filter(isString); // string[]
const functions = mixedArray.filter(isFunction); // ((...args: any[]) => any)[]
const nonNil = mixedArray.filter(isNotNil); // Exclude<unknown, null | undefined>[]