Open In App

How to Deep Clone an Object & Preserve its Type with TypeScript ?

Last Updated : 01 Aug, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

In TypeScript, deep cloning an object by preserving its type consists of retaining the same structure and type information as of original object.

Below are the approaches to Deep Clone an Object & Preserve its Type:

Using JSON.stringify and JSON.parse

In this approach, we are using the JSON.stringify and JSON.parse functions to perform a deep clone of the object. The DeepClone<T> type makes sure that the original object type structure is preserved during the cloning process, which is checked using instanceOf, and the boolean value is stored and printed from (preserveRes) variable.

Syntax:

JSON.stringify(value, replacer, space);
JSON.parse( string, function )

Example: The below example uses JSON.stringify and JSON.parse to deep-clone an object and preserve its type with TypeScript.

JavaScript
type DeepClone<T> = T extends object ? { 
    [K in keyof T]: DeepClone<T[K]> } : T;
function approach1Fn<T>(obj: T): DeepClone<T> {
    return JSON.parse(JSON.stringify(obj));
}
interface Person {
    name: string;
    age: number;
}
const person: Person = { name: 'GeeksforGeeks', age: 23 };
const res = approach1Fn(person);
console.log(res);
const preserveRes: boolean = res instanceof Object;
console.log('Type is preserved:', preserveRes);

Output:

{ name: 'GeeksforGeeks', age: 23 }
Type is preserved: true

Using Object.Assign function

In this approach, we are using the Object.assign() function for deep cloning by recursively traversing object properties and creating a new object. Type preservation is preserved through a subsequent type assertion (as T), as verified by checking the cloned result's instance of an object (preserveRes instanceof Object).

Syntax:

Object.assign(target, ...sources);

Example: The below example uses Object.assign function to Deep Clone an Object and Preserve its Type with TypeScript.

JavaScript
function approach2Fn<T>(obj: T): T {
    if (typeof obj !== 'object' || obj === null) {
        return obj;
    }
    const res: any = Array
        .isArray(obj) ? [] : {};
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            res[key] = approach2Fn(obj[key]);
        }
    }
    return Object.assign(res, obj) as T;
}
interface Person {
    name: string;
    website: string;
}
const per: Person =
{
    name: 'GeeksforGeeks',
    website: 'www.geeksforgeeks.org'
};
const res = approach2Fn(per);
console.log(res);
const preserveRes: boolean = res instanceof Object;
console.log('Type is preserved:', preserveRes);

Output:

{ name: 'GeeksforGeeks', website: 'www.geeeksforgeeks.org' }
Type is preserved: true

Using Lodash's cloneDeep function

In this approach, we are using Lodash's cloneDeep function to perform a deep clone of the object. Lodash's cloneDeep method is a robust solution for deep cloning objects, and TypeScript's type inference ensures that the type is preserved.

Syntax:

_.cloneDeep(value);

Example:

JavaScript
import _ from 'lodash';

function approach3Fn<T>(obj: T): T {
    return _.cloneDeep(obj);
}

interface Person {
    name: string;
    details: {
        age: number;
        address: {
            city: string;
            country: string;
        };
    };
}

const person: Person = {
    name: 'GeeksforGeeks',
    details: {
        age: 22,
        address: {
            city: 'Noida',
            country: 'India'
        }
    }
};

const res = approach3Fn(person);
console.log(res);

const preserveRes: boolean = res instanceof Object;
console.log('Type is preserved:', preserveRes);

Output:

{
name: 'GeeksforGeeks',
details: {
age: 22,
address: {
city: 'Noida',
country: 'India'
}
}
}
Type is preserved: true

Using a Recursive Function

In this approach, we manually implement a recursive function to deep clone the object. This method allows us to handle more complex cloning requirements and ensure that the type structure of the original object is preserved.

Example: The below example uses a custom recursive function to deep-clone an object and preserve its type with TypeScript.

JavaScript
interface Person {
  name: string;
  details: {
    age: number;
    address: {
      city: string;
      country: string;
    };
  };
}

const person: Person = {
  name: 'GeeksforGeeks',
  details: {
    age: 22,
    address: {
      city: 'Noida',
      country: 'India'
    }
  }
};

const clonedPerson = deepClone(person);

const preserveRes = clonedPerson instanceof Object;

console.log(clonedPerson);
console.log("Type is preserved:", preserveRes);

Output:

{
name: 'GeeksforGeeks',
details: {
age: 22,
address: {
city: 'Noida',
country: 'India'
}
}
}
Type is preserved: true

Next Article

Similar Reads