-
Notifications
You must be signed in to change notification settings - Fork 0
/
clone.util.ts
61 lines (53 loc) · 1.87 KB
/
clone.util.ts
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import { areIdentical, isNull } from "../object/object.util";
import { CloneError } from "../error/clone.error";
/**
* Clones the provided argument.
* "Techniques" for differing variables:
* - array: [...spread]
* - boolean: Boolean(value)
* - object: { ...spread }
* - number: number. (primitive, correct? has no reference)
* - string: interpolation (cheeky)
*
* Do not ask me why spread. I will add a note in TECH.md
*
* @param argument to be cloned.
*/
export function clone(argument: unknown | unknown[]): unknown {
if (Array.isArray(argument)) {
return [...argument];
}
switch (typeof argument) {
case "boolean":
return Boolean(argument);
case "undefined":
return undefined;
case "object":
// null = "nothing" (does not exist).
// unfortunately typeof null is object in JS. consider it a bug.
return isNull(argument) ? null : { ...argument };
case "number":
return argument;
case "string":
return `${ argument }`;
}
throw new CloneError("what have you given me?");
}
/**
* Same as above but provides an extra layer of "reassurance".
* Was the clone successful? Are the objects identical - according to me?
* Do you want to run an identity check using my areIdentical function, free
* of charge?
*
* @param argument to be cloned and subsequently validated against its clone
* @throws CloneError if the argument is not identical to its clone
*/
export function cloneWithValidation(argument: unknown | unknown[]): unknown {
const argumentClone: unknown = clone(argument);
areIdentical(argument, argument);
const argumentsIdentical: boolean = areIdentical(argument, argumentClone);
if (!argumentsIdentical) {
throw new CloneError("the cloned object is not identical to the original");
}
return clone;
}