or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

collections.mdform-utilities.mdindex.mdobject-operations.mdreactive-patterns.mdstring-processing.mdtype-checking.mdvalidation.md
tile.json

object-operations.mddocs/

Object Operations

Advanced object manipulation including deep cloning, merging, and equality comparison with special handling for React elements, Moment objects, and Immutable.js objects. These utilities are optimized for form data processing and complex object structures.

Capabilities

Deep Equality Comparison

Fast deep equality comparison with special handling for common JavaScript objects and libraries.

/**
 * Perform deep equality comparison between two values
 * Handles special cases: React elements, Moment objects, Immutable.js, Date, RegExp, URL objects
 * @param a - First value to compare
 * @param b - Second value to compare
 * @returns True if values are deeply equal
 */
function isEqual(a: any, b: any): boolean;

Usage Examples:

import { isEqual } from "@formily/shared";

// Basic equality
console.log(isEqual(1, 1));                    // true
console.log(isEqual("hello", "hello"));        // true
console.log(isEqual([1, 2, 3], [1, 2, 3]));   // true

// Object equality
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { a: 1, b: { c: 2 } };
const obj3 = { a: 1, b: { c: 3 } };

console.log(isEqual(obj1, obj2)); // true
console.log(isEqual(obj1, obj3)); // false

// Array equality
console.log(isEqual([1, [2, 3]], [1, [2, 3]])); // true
console.log(isEqual([1, [2, 3]], [1, [2, 4]])); // false

// Date equality
const date1 = new Date("2023-01-01");
const date2 = new Date("2023-01-01");
const date3 = new Date("2023-01-02");

console.log(isEqual(date1, date2)); // true
console.log(isEqual(date1, date3)); // false

// RegExp equality
console.log(isEqual(/abc/g, /abc/g)); // true
console.log(isEqual(/abc/g, /abc/i)); // false

// Special handling for React elements (prevents circular reference issues)
import React from "react";
const element1 = React.createElement("div", { id: "test" });
const element2 = React.createElement("div", { id: "test" });
// Compares elements safely without traversing _owner properties

Object Cloning

Deep and shallow cloning operations with special handling for complex objects.

/**
 * Create a shallow copy of the value
 * Special handling for: React elements, BigNumber, Moment objects, JSON Schema objects, Immutable.js
 * @param values - Value to clone
 * @returns Shallow copy of the value
 */
function shallowClone(values: any): any;

/**
 * Create a deep copy of the value
 * Special handling for: React elements, BigNumber, Moment objects, JSON Schema objects, Immutable.js
 * @param values - Value to clone
 * @returns Deep copy of the value
 */
function clone(values: any): any;

Usage Examples:

import { clone, shallowClone } from "@formily/shared";

// Shallow cloning
const original = { a: 1, b: { c: 2 } };
const shallow = shallowClone(original);

shallow.a = 10;           // Doesn't affect original
shallow.b.c = 20;         // Affects original (shared reference)

console.log(original.a);  // 1 (unchanged)
console.log(original.b.c); // 20 (changed, shared reference)

// Deep cloning
const deep = clone(original);

deep.a = 100;             // Doesn't affect original
deep.b.c = 200;           // Doesn't affect original

console.log(original.a);  // 1 (unchanged)
console.log(original.b.c); // 2 (unchanged, separate reference)

// Array cloning
const arr = [1, { x: 2 }, [3, 4]];
const clonedArr = clone(arr);

clonedArr[1].x = 99;      // Doesn't affect original
clonedArr[2][0] = 88;     // Doesn't affect original

console.log(arr[1].x);    // 2 (unchanged)
console.log(arr[2][0]);   // 3 (unchanged)

// Special object handling
const moment = require("moment");
const momentObj = moment("2023-01-01");

// These objects are handled specially and returned as-is or converted appropriately
const clonedMoment = clone(momentObj);
const reactElement = React.createElement("div");
const clonedElement = clone(reactElement); // Returns same reference

// Immutable.js objects
const immutableMap = Immutable.Map({ a: 1, b: 2 });
const clonedImmutable = clone(immutableMap); // Calls toJS() method

Object Merging

Deep merging utilities with flexible configuration options.

/**
 * Deep merge objects and arrays with configurable options
 * @param target - Target object to merge into
 * @param source - Source object to merge from
 * @param options - Merge configuration options
 * @returns Merged result
 */
function merge(target: any, source: any, options?: MergeOptions): any;

/**
 * Lazy merge using Proxy for deferred evaluation
 * Useful for merging functions or objects that should be evaluated on access
 * @param target - Target object/function
 * @param args - Additional objects/functions to merge
 * @returns Proxy object that merges on property access
 */
function lazyMerge<T extends object | Function>(target: T, ...args: T[]): any;

interface MergeOptions {
  arrayMerge?(target: any[], source: any[], options?: MergeOptions): any[];
  clone?: boolean;
  assign?: boolean;
  customMerge?(key: string, options?: MergeOptions): ((x: any, y: any) => any) | undefined;
  isMergeableObject?(value: object): boolean;
  cloneUnlessOtherwiseSpecified?: (value: any, options: MergeOptions) => any;
}

Usage Examples:

import { merge, lazyMerge } from "@formily/shared";

// Basic object merging
const target = { a: 1, b: { x: 10 } };
const source = { b: { y: 20 }, c: 3 };

const merged = merge(target, source);
// Result: { a: 1, b: { x: 10, y: 20 }, c: 3 }

// Array merging (default: concatenation)
const arr1 = { items: [1, 2] };
const arr2 = { items: [3, 4] };

const mergedArrays = merge(arr1, arr2);
// Result: { items: [1, 2, 3, 4] }

// Custom array merge strategy
const customMerged = merge(arr1, arr2, {
  arrayMerge: (target, source) => source // Replace instead of concat
});
// Result: { items: [3, 4] }

// Assign mode (modify target in place)
const original = { a: 1 };
const result = merge(original, { b: 2 }, { assign: true });
// original is now { a: 1, b: 2 }
// result === original (same reference)

// Lazy merging with functions
const config1 = () => ({ database: { host: "localhost" } });
const config2 = () => ({ database: { port: 5432 } });

const lazyConfig = lazyMerge(config1, config2);

// Functions are called only when properties are accessed
console.log(lazyConfig.database.host); // "localhost"
console.log(lazyConfig.database.port); // 5432

// Lazy merging with objects
const defaults = { theme: "light", size: "medium" };
const userPrefs = () => ({ theme: "dark" });

const settings = lazyMerge(defaults, userPrefs);
console.log(settings.theme); // "dark" (from userPrefs function)
console.log(settings.size);  // "medium" (from defaults object)

Advanced Merging Examples

import { merge } from "@formily/shared";

// Form configuration merging
const defaultFormConfig = {
  validation: {
    required: true,
    minLength: 0
  },
  ui: {
    placeholder: "Enter value",
    disabled: false
  }
};

const fieldConfig = {
  validation: {
    minLength: 5,
    maxLength: 100
  },
  ui: {
    disabled: true
  }
};

const finalConfig = merge(defaultFormConfig, fieldConfig);
/*
Result: {
  validation: {
    required: true,      // from default
    minLength: 5,        // from field (overrides default)
    maxLength: 100       // from field (new)
  },
  ui: {
    placeholder: "Enter value", // from default
    disabled: true              // from field (overrides default)
  }
}
*/

// Custom merge function for specific keys
const config1 = { features: ["auth", "api"] };
const config2 = { features: ["ui", "db"] };

const customMerged = merge(config1, config2, {
  customMerge: (key) => {
    if (key === "features") {
      return (target, source) => [...new Set([...target, ...source])]; // Union
    }
    return undefined; // Use default merge for other keys
  }
});
// Result: { features: ["auth", "api", "ui", "db"] }

// Preventing cloning for performance
const largeObject = { /* large data structure */ };
const addition = { newField: "value" };

const efficientMerge = merge(largeObject, addition, {
  clone: false // Don't clone existing properties
});

Special Object Handling

The object operations in @formily/shared include special handling for various JavaScript objects and libraries:

  • React Elements: Detected via $$typeof and _owner properties, handled safely to avoid circular references
  • Moment Objects: Detected via _isAMomentObject, handled appropriately for date operations
  • Immutable.js Objects: Detected via toJS method, converted to plain objects when cloning
  • JSON Schema Objects: Detected via _isJSONSchemaObject, handled specially
  • BigNumber Objects: Detected via _isBigNumber, preserved during cloning
  • Objects with toJSON: Use toJSON() method when available for serialization

This makes the utilities particularly well-suited for complex form applications that may use various JavaScript libraries and frameworks.