CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-es-toolkit

A state-of-the-art, high-performance JavaScript utility library with a small bundle size and strong type annotations.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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

Install with Tessl CLI

npx tessl i tessl/npm-es-toolkit

docs

array.md

compat.md

error.md

function.md

index.md

math.md

object.md

predicate.md

promise.md

string.md

util.md

tile.json