All files / toolbox / clone.ts

100.00% Branches 12/12
100.00% Lines 19/19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
 
 
 
 
 
 
x1
x31
x33
x33
x385
x36
x36
x31
x37
x37
x46
x48
x48
x53
x53
x37
x37
x48
x31























/**
 * Clones a value deeply.
 *
 * If `structuredCloneable` is set, the clone will be compatible with `structuredClone` algorithm, meaning that:
 * - Proxy are unproxyed to plain objects
 * - Incompatible types are ignored
 */
export function clone<T>(value: T, options?: { structuredCloneable?: boolean }): T {
  if (Array.isArray(value)) {
    return value.map((item) => clone(item)) as T
  }
  if ([Date, Error, Map, Set, RegExp].some((type) => value instanceof type)) {
    return structuredClone(value) as T
  }
  if ((typeof value === "object") && (value !== null)) {
    const cloned = {} as Record<PropertyKey, unknown>
    for (const [k, v] of Object.entries(value)) {
      if ((options?.structuredCloneable) && (typeof v === "symbol" || typeof v === "function")) {
        continue
      }
      cloned[k] = clone(v, options)
    }
    return cloned as T
  }
  return value as T
}