Skip to content

Instantly share code, notes, and snippets.

@erikvullings
Last active September 3, 2024 09:02
Show Gist options
  • Save erikvullings/ada7af09925082cbb89f40ed962d475e to your computer and use it in GitHub Desktop.
Save erikvullings/ada7af09925082cbb89f40ed962d475e to your computer and use it in GitHub Desktop.
Deep copy or clone in TypeScript
/**
* Deep copy function for TypeScript.
* @param T Generic type of target/copied value.
* @param target Target value to be copied.
* @see Source project, ts-deepcopy https://github.com/ykdr2017/ts-deepcopy
* @see Code pen https://codepen.io/erikvullings/pen/ejyBYg
*/
export const deepCopy = <T>(target: T): T => {
if (target === null) {
return target;
}
if (target instanceof Date) {
return new Date(target.getTime()) as any;
}
if (target instanceof Array) {
const cp = [] as any[];
(target as any[]).forEach((v) => { cp.push(v); });
return cp.map((n: any) => deepCopy<any>(n)) as any;
}
if (typeof target === 'object' && target !== {}) {
const cp = { ...(target as { [key: string]: any }) } as { [key: string]: any };
Object.keys(cp).forEach(k => {
cp[k] = deepCopy<any>(cp[k]);
});
return cp as T;
}
return target;
};
@MohammadFakhreddin
Copy link

MohammadFakhreddin commented Jan 27, 2020

I guess its related to your typescript version because it works fine in Typescript "3.5.3". If you are not using something like realmdb original solution works fine. But for quick workaround you can trick your compiler in the following way:

(Symbol as any).iterator

I updated the posted code as well

@arg23
Copy link

arg23 commented Feb 3, 2020

Thank you so much!!!!

@erikvullings
Copy link
Author

@fvigotti
Indeed, the ObjectHelper is missing part of the type info. However, this can be easily added, as you can see here.

@vroshupkin
Copy link

vroshupkin commented Jan 31, 2023

This working with array, objects and persist datatype

function deepCopyObj<T>(obj: T): T { return JSON.parse(JSON.stringify(obj)) as T; }

@dominikbrazdil
Copy link

I faced an issue when cloning object which had empty objects inside - the empty objects were only passed by reference and therefore any change to the new object affected the old one. I removed the 'target !== {}' to make it work for me. @erikvullings was there any other reason except from optimization for having the condition there?

@erikvullings
Copy link
Author

This working with array, objects and persist datatype

function deepCopyObj<T>(obj: T): T { return JSON.parse(JSON.stringify(obj)) as T; }

True, but it is a rather expensive operation, and it will fail on circular objects, i.e. objects referring to itself.

@erikvullings
Copy link
Author

I faced an issue when cloning object which had empty objects inside - the empty objects were only passed by reference and therefore any change to the new object affected the old one. I removed the 'target !== {}' to make it work for me. @erikvullings was there any other reason except from optimization for having the condition there?

No, not really - this copy/clone function is for basic usage only. I've also ported it to a more elaborate version that takes care of several other issues too, deep-copy-ts. Or you can get it from npm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment