Skip to content

Commit b665b48

Browse files
test(helpers): refactor and improve decycle
1 parent d1c5314 commit b665b48

1 file changed

Lines changed: 39 additions & 29 deletions

File tree

__tests__/helpers/decycle.ts

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -75,55 +75,65 @@ function deepCopy(
7575
visitedObjects: WeakMap<object, string>,
7676
replacer?: ReplacerFunction,
7777
): unknown {
78-
let existingPath: string | undefined;
79-
let copy: unknown[] | DecycledObject;
80-
81-
if (replacer !== undefined) {
78+
if (typeof replacer === 'function') {
8279
value = replacer(value);
8380
}
8481

85-
if (
86-
typeof value === 'object' &&
87-
value !== null &&
88-
!(value instanceof Boolean) &&
89-
!(value instanceof Date) &&
90-
!(value instanceof Number) &&
91-
!(value instanceof RegExp) &&
92-
!(value instanceof String)
93-
) {
94-
existingPath = visitedObjects.get(value);
82+
if (isPlainObjectOrArray(value)) {
83+
const existingPath = visitedObjects.get(value);
84+
9585
if (existingPath !== undefined) {
9686
return { $ref: existingPath };
9787
}
9888

9989
visitedObjects.set(value, path);
10090

10191
if (Array.isArray(value)) {
102-
copy = [];
103-
(value as unknown[]).forEach((element: unknown, index: number) => {
104-
(copy as unknown[])[index] = deepCopy(
92+
const copy: unknown[] = [];
93+
value.forEach((element, index) => {
94+
copy[index] = deepCopy(
10595
element,
10696
`${path}[${index.toString()}]`,
10797
visitedObjects,
10898
replacer,
10999
);
110100
});
111-
} else {
112-
copy = {} as DecycledObject;
113-
Object.keys(value as Record<string, unknown>).forEach(function (
114-
key: string,
115-
) {
116-
(copy as DecycledObject)[key] = deepCopy(
117-
(value as Record<string, unknown>)[key],
118-
`${path}[${JSON.stringify(key)}]`,
119-
visitedObjects,
120-
replacer,
121-
);
122-
});
101+
return copy;
123102
}
124103

104+
const record = value as Record<string, unknown>;
105+
const copy: DecycledObject = {};
106+
107+
Object.keys(record).forEach((key) => {
108+
copy[key] = deepCopy(
109+
record[key],
110+
`${path}[${JSON.stringify(key)}]`,
111+
visitedObjects,
112+
replacer,
113+
);
114+
});
115+
125116
return copy;
126117
}
127118

128119
return value;
129120
}
121+
122+
/**
123+
* Checks whether a value is a plain object or array (not a primitive or
124+
* built-in wrapper like `Boolean`, `Date`, `Number`, `RegExp`, or `String`).
125+
*
126+
* @param value - The value to check.
127+
* @returns `true` if the value is a plain object or array.
128+
*/
129+
function isPlainObjectOrArray(value: unknown): value is object {
130+
return (
131+
typeof value === 'object' &&
132+
value !== null &&
133+
!(value instanceof Boolean) &&
134+
!(value instanceof Date) &&
135+
!(value instanceof Number) &&
136+
!(value instanceof RegExp) &&
137+
!(value instanceof String)
138+
);
139+
}

0 commit comments

Comments
 (0)