UNPKG

@tienedev/datype

Version:

Modern TypeScript utility library with pragmatic typing and zero dependencies

93 lines (90 loc) 2.68 kB
'use strict'; /** * Creates a deep clone of the given value, recursively cloning nested objects and arrays. * Handles circular references and preserves object types. * * @template T - The type of the value to clone * @param value - The value to clone * @returns A deep clone of the input value * * @example * ```typescript * import { cloneDeep } from 'datype'; * * const original = { * name: 'John', * hobbies: ['reading', 'coding'], * address: { city: 'Paris', zip: '75001' } * }; * * const cloned = cloneDeep(original); * cloned.address.city = 'London'; * * console.log(original.address.city); // 'Paris' (unchanged) * console.log(cloned.address.city); // 'London' * ``` */ function cloneDeep(value, seen = new WeakMap()) { // Handle null and undefined if (value === null || value === undefined) { return value; } // Handle primitive types if (typeof value !== 'object') { return value; } // Handle circular references if (seen.has(value)) { return seen.get(value); } // Handle Date objects if (value instanceof Date) { return new Date(value.getTime()); } // Handle RegExp objects if (value instanceof RegExp) { return new RegExp(value.source, value.flags); } // Handle Arrays if (Array.isArray(value)) { const clonedArray = []; seen.set(value, clonedArray); for (let i = 0; i < value.length; i++) { clonedArray[i] = cloneDeep(value[i], seen); } return clonedArray; } // Handle Set objects if (value instanceof Set) { const clonedSet = new Set(); seen.set(value, clonedSet); for (const item of Array.from(value)) { clonedSet.add(cloneDeep(item, seen)); } return clonedSet; } // Handle Map objects if (value instanceof Map) { const clonedMap = new Map(); seen.set(value, clonedMap); for (const [key, val] of Array.from(value)) { clonedMap.set(cloneDeep(key, seen), cloneDeep(val, seen)); } return clonedMap; } // Handle plain objects if (typeof value === 'object') { const clonedObject = {}; seen.set(value, clonedObject); // Copy all enumerable properties (including inherited ones) for (const key in value) { if (Object.prototype.hasOwnProperty.call(value, key)) { clonedObject[key] = cloneDeep(value[key], seen); } } return clonedObject; } // For other types (functions, etc.), return as-is return value; } exports.cloneDeep = cloneDeep;