or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

array.mdcompat.mderror.mdfunction.mdindex.mdmath.mdobject.mdpredicate.mdpromise.mdstring.mdutil.md
tile.json

predicate.mddocs/

Type Guards and Predicates

Comprehensive type checking functions providing TypeScript type guards for runtime type validation. Essential for type-safe JavaScript development and runtime type checking.

Capabilities

Null and Undefined Checks

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));        // false

Basic Type Guards

Functions 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);
  }
}

Object Type Guards

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;
}

Collection Type Guards

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;
}

Array and Buffer Type Guards

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;
}

Web API Type Guards

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;
}

Environment Detection

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: () => {} };
}

Promise and Async Type Guards

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); // 10

JSON Type Guards

Functions 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');
}

Equality and Comparison

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)); // true

Type Guard Patterns

Chaining Type Guards

import { 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');
}

Type-Safe Array Filtering

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>[]