Skip to content

Instantly share code, notes, and snippets.

@vikiboss
Created April 4, 2023 12:10
Show Gist options
  • Save vikiboss/4f2f9571b7233204ef5f96e4ba73e78c to your computer and use it in GitHub Desktop.
Save vikiboss/4f2f9571b7233204ef5f96e4ba73e78c to your computer and use it in GitHub Desktop.
Deep Clone for TS
function isObject(obj: unknown): obj is Record<string, unknown> {
return typeof obj === 'object' && obj !== null
}
export function deepClone<T>(obj: T, cache: Map<unknown, unknown> = new Map()): T {
if (obj === null || typeof obj !== 'object') {
return obj
}
if (cache.has(obj)) {
return cache.get(obj) as T
}
let result: unknown
if (obj instanceof Date) {
result = new Date(obj.getTime())
} else if (obj instanceof Buffer) {
result = Buffer.from(obj)
} else if (ArrayBuffer.isView(obj) && obj.buffer instanceof ArrayBuffer) {
result = (obj as unknown as ArrayBuffer).slice(0)
} else if (obj instanceof Map) {
const resultMap = new Map()
cache.set(obj, resultMap)
for (const [key, value] of obj.entries()) {
resultMap.set(deepClone(key, cache), deepClone(value, cache))
}
result = resultMap
} else if (obj instanceof Set) {
const resultSet = new Set()
cache.set(obj, resultSet)
for (const value of obj.values()) {
resultSet.add(deepClone(value, cache))
}
result = resultSet
} else if (typeof obj === 'function') {
result = obj
} else if (isObject(obj)) {
const newObj: Record<string, unknown> = {}
cache.set(obj, newObj)
Object.keys(obj).forEach(key => {
newObj[key] = deepClone(obj[key], cache)
})
result = newObj
} else {
result = obj
}
return result as T
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment