Deep CloneAPI Reference

API Reference

Complete API documentation for @visulima/deep-clone

Last updated:

API Reference

Complete reference for all functions and types in the @visulima/deep-clone package.

Main Function

deepClone

Creates a deep clone of the input data with circular reference handling.

Signature:

function deepClone<T>(
  originalData: T,
  options?: Options
): DeepReadwrite<T>

Type Parameters:

  • T - The type of the original data

Parameters:

  • originalData (T, required) - The data to clone (any type)
  • options (Options, optional) - Cloning configuration options

Returns: DeepReadwrite<T> - A deep cloned copy with readonly modifiers removed

Example:

import { deepClone } from "@visulima/deep-clone";

const original = {
  name: "Alice",
  age: 30,
  nested: { city: "NYC" }
};

const cloned = deepClone(original);
cloned.nested.city = "LA";

console.log(original.nested.city); // "NYC" (unchanged)
console.log(cloned.nested.city);   // "LA"

Options

Options Interface

Configuration options for the deepClone function.

Type Definition:

interface Options {
  strict?: boolean;
  handler?: Partial<HandlerMap>;
}

Properties:

strict

Controls whether to copy non-enumerable properties and symbols.

  • Type: boolean
  • Default: false
  • Description:
    • false (loose mode): Only copies enumerable properties (faster)
    • true (strict mode): Copies all properties including non-enumerable and symbols (slower)

Example:

import { deepClone } from "@visulima/deep-clone";

const obj = { visible: "enumerable" };
Object.defineProperty(obj, "hidden", {
  value: "non-enumerable",
  enumerable: false
});

// Loose mode (default)
const loose = deepClone(obj);
console.log(loose.hidden); // undefined

// Strict mode
const strict = deepClone(obj, { strict: true });
console.log(strict.hidden); // "non-enumerable"

handler

Custom handlers for specific data types.

  • Type: Partial<HandlerMap>
  • Default: undefined
  • Description: Override default cloning behavior for specific types

HandlerMap Definition:

type InternalHandler<T> = (object: T, state: State) => T;

interface HandlerMap {
  Array: InternalHandler<unknown[]>;
  ArrayBuffer: InternalHandler<ArrayBuffer>;
  Blob: InternalHandler<Blob>;
  DataView: InternalHandler<DataView>;
  Date: InternalHandler<Date>;
  Error: InternalHandler<Error>;
  Function: InternalHandler<Function>;
  Map: InternalHandler<Map<unknown, unknown>>;
  Object: InternalHandler<Record<string, unknown>>;
  Promise: InternalHandler<Promise<unknown>>;
  RegExp: InternalHandler<RegExp>;
  Set: InternalHandler<Set<unknown>>;
  SharedArrayBuffer: InternalHandler<SharedArrayBuffer>;
  WeakMap: InternalHandler<WeakMap<any, unknown>>;
  WeakSet: InternalHandler<WeakSet<any>>;
}

Example:

import { deepClone } from "@visulima/deep-clone";
import type { State } from "@visulima/deep-clone";

const cloned = deepClone(data, {
  handler: {
    Date: (date: Date, _state: State) => {
      // Clone to current time instead of original time
      return new Date();
    },
    Array: (array: unknown[], state: State) => {
      // Custom array cloning (e.g., filter nulls)
      const filtered = array.filter(item => item !== null);
      return filtered.map(item => state.clone(item, state));
    }
  }
});

State Interface

The state object passed to custom handlers.

Type Definition:

interface State {
  cache: WeakMap<any, any>;
  clone: (value: any, state: State) => any;
}

Properties:

  • cache (WeakMap<any, any>) - Circular reference tracking cache
  • clone (function) - The clone function to recursively clone nested values

Usage in Custom Handlers:

import { deepClone } from "@visulima/deep-clone";
import type { State } from "@visulima/deep-clone";

const cloned = deepClone(data, {
  handler: {
    Object: (obj: Record<PropertyKey, unknown>, state: State) => {
      // Create empty object
      const copy = {} as Record<PropertyKey, unknown>;

      // Clone each property using state.clone
      for (const key in obj) {
        copy[key] = state.clone(obj[key], state);
      }

      return copy;
    }
  }
});

Utility Functions

copyOwnProperties

Copies all own enumerable properties from an object (shallow copy).

Signature:

function copyOwnProperties<T extends object>(object: T): T

Parameters:

  • object (T, required) - The object to copy properties from

Returns: T - A new object with copied properties

Note: This performs a shallow copy. Nested objects are referenced, not cloned.

Example:

import { copyOwnProperties } from "@visulima/deep-clone/utils";

const original = {
  name: "Alice",
  age: 30,
  address: { city: "NYC" }
};

const copy = copyOwnProperties(original);
copy.age = 31;
copy.address.city = "LA";

console.log(original.age);          // 30 (unchanged)
console.log(original.address.city); // "LA" (changed! shallow copy)

getCleanClone

Creates an empty object with the same prototype as the input object.

Signature:

function getCleanClone<T extends object>(object: T): T

Parameters:

  • object (T, required) - The object to get a clean clone of

Returns: T - An empty object with the same prototype

Example:

import { getCleanClone } from "@visulima/deep-clone/utils";

class User {
  name: string = "";
  age: number = 0;

  greet() {
    return `Hello, ${this.name}!`;
  }
}

const user = new User();
user.name = "Alice";
user.age = 30;

const clean = getCleanClone(user);

console.log(clean.name);             // "" (empty)
console.log(clean.age);              // 0 (default)
console.log(clean.greet());          // "Hello, !" (method exists)
console.log(clean instanceof User);  // true

Use Case: Useful when you need an empty instance of the same class/prototype without manually calling constructors.


Type Definitions

DeepReadwrite

Utility type that recursively removes readonly modifiers from all properties.

Type Definition:

type DeepReadwrite<T> = T extends object | []
  ? { -readonly [P in keyof T]: DeepReadwrite<T[P]> }
  : T

Description: The cloned object has all readonly modifiers removed, allowing mutations.

Example:

import { deepClone } from "@visulima/deep-clone";

interface ReadonlyData {
  readonly id: number;
  readonly config: {
    readonly enabled: boolean;
  };
}

const data: ReadonlyData = {
  id: 1,
  config: { enabled: true }
};

// TypeScript error: Cannot assign to 'id' because it is a read-only property
// data.id = 2;

const cloned = deepClone(data);

// OK! DeepReadwrite removes readonly
cloned.id = 2;
cloned.config.enabled = false;

Supported Types Reference

Fully Supported Types

These types are deeply cloned with full support:

TypeBehavior
undefinedReturned as-is (immutable)
nullReturned as-is (immutable)
booleanReturned as-is (immutable)
numberReturned as-is (immutable)
stringReturned as-is (immutable)
ObjectDeep cloned with all nested properties
ArrayDeep cloned with all elements
DateNew Date instance with same timestamp
RegExpNew RegExp with same pattern and flags
MapNew Map with cloned entries
SetNew Set with cloned values
ErrorNew Error with cloned properties and stack
ArrayBufferNew ArrayBuffer with copied bytes
Uint8ArrayNew Uint8Array with copied data
Int8ArrayNew Int8Array with copied data
Uint16ArrayNew Uint16Array with copied data
Int16ArrayNew Int16Array with copied data
Uint32ArrayNew Uint32Array with copied data
Int32ArrayNew Int32Array with copied data
Float32ArrayNew Float32Array with copied data
Float64ArrayNew Float64Array with copied data
Uint8ClampedArrayNew Uint8ClampedArray with copied data
DataViewNew DataView with cloned buffer
BlobNew Blob with same content (browser)
BufferNew Buffer with copied data (Node.js)
FunctionCopied by reference (not cloned)
DOM NodesCloned using element.cloneNode(true)

Unsupported Types

These types throw TypeError when cloned:

TypeError Message
Promise"Promise objects cannot be cloned"
WeakMap"WeakMap objects cannot be cloned"
WeakSet"WeakSet objects cannot be cloned"
SharedArrayBuffer"SharedArrayBuffer objects cannot be cloned"

Example:

import { deepClone } from "@visulima/deep-clone";

try {
  deepClone(new Promise(resolve => resolve(1)));
} catch (error) {
  console.log(error.message);
  // "Promise objects cannot be cloned"
}

Error Handling

TypeError

Thrown when attempting to clone unsupported types.

Example:

import { deepClone } from "@visulima/deep-clone";

try {
  const weakMap = new WeakMap();
  deepClone(weakMap);
} catch (error) {
  console.log(error instanceof TypeError); // true
  console.log(error.message);              // "WeakMap objects cannot be cloned"
}

Circular References

Circular references are automatically handled and do not throw errors:

import { deepClone } from "@visulima/deep-clone";

const obj: any = { name: "circular" };
obj.self = obj; // Circular reference

const cloned = deepClone(obj); // No error!
console.log(cloned.self === cloned); // true

Function Summary

FunctionCategoryDescription
deepCloneMainDeep clone any value with circular reference handling
copyOwnPropertiesUtilityShallow copy of object's own properties
getCleanCloneUtilityCreate empty object with same prototype

Type Export Summary

TypeDescription
OptionsConfiguration options for deepClone
StateState object for custom handlers
DeepReadwrite<T>Removes readonly modifiers recursively

Next Steps

Usage Guide

Learn how to use deepClone with detailed examples

Back to Overview

Return to package overview

Support

Contribute to our work and keep us going

Community is the heart of open source. The success of our packages wouldn't be possible without the incredible contributions of users, testers, and developers who collaborate with us every day.Want to get involved? Here are some tips on how you can make a meaningful impact on our open source projects.

Ready to help us out?

Be sure to check out the package's contribution guidelines first. They'll walk you through the process on how to properly submit an issue or pull request to our repositories.

Submit a pull request

Found something to improve? Fork the repo, make your changes, and open a PR. We review every contribution and provide feedback to help you get merged.

Good first issues

Simple issues suited for people new to open source development, and often a good place to start working on a package.
View good first issues