@qntm-code/utils
Version:
A collection of useful utility functions with associated TypeScript types. All functions have been unit tested.
107 lines (106 loc) • 4.02 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.clone = void 0;
const isPlainObject_js_1 = require("../type-predicates/isPlainObject.js");
const typeOf_js_1 = require("../type-predicates/typeOf.js");
/**
* Recursively (deep) clones native types, like Object, Array, RegExp, Date, Map, Set, Symbol, Error as well as primitives.
*/
function clone(value, instanceClone = false) {
switch ((0, typeOf_js_1.typeOf)(value)) {
case typeOf_js_1.ValueType.object: {
return cloneObjectDeep(value, instanceClone);
}
case typeOf_js_1.ValueType.array:
case typeOf_js_1.ValueType.int8array:
case typeOf_js_1.ValueType.uint8array:
case typeOf_js_1.ValueType.uint8clampedarray:
case typeOf_js_1.ValueType.int16array:
case typeOf_js_1.ValueType.uint16array:
case typeOf_js_1.ValueType.int32array:
case typeOf_js_1.ValueType.uint32array:
case typeOf_js_1.ValueType.float32array:
case typeOf_js_1.ValueType.float64array:
case typeOf_js_1.ValueType.bigint64array:
case typeOf_js_1.ValueType.biguint64array: {
return cloneArrayDeep(value, instanceClone);
}
default: {
return cloneShallow(value);
}
}
}
exports.clone = clone;
function cloneShallow(value) {
switch ((0, typeOf_js_1.typeOf)(value)) {
case typeOf_js_1.ValueType.buffer: {
return cloneBuffer(value);
}
case typeOf_js_1.ValueType.symbol: {
return cloneSymbol(value);
}
case typeOf_js_1.ValueType.error: {
return Object.create(value);
}
case typeOf_js_1.ValueType.map: {
return new Map(value);
}
case typeOf_js_1.ValueType.set: {
return new Set(value);
}
case typeOf_js_1.ValueType.date: {
return new Date(value);
}
case typeOf_js_1.ValueType.regexp: {
return cloneRegExp(value);
}
case typeOf_js_1.ValueType.moment: {
return value.clone();
}
}
return value;
}
function cloneObjectDeep(value, instanceClone) {
if (typeof instanceClone === 'function') {
return instanceClone(value);
}
if (instanceClone || (0, isPlainObject_js_1.isPlainObject)(value)) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
const cloned = new value.constructor();
for (const key in value) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
cloned[key] = clone(value[key]);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return cloned;
}
return value;
}
function cloneArrayDeep(value, instanceClone) {
const length = value.length;
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
const cloned = new value.constructor(length);
for (let i = 0; i < length; i++) {
cloned[i] = clone(value[i], instanceClone);
}
return cloned;
}
function cloneRegExp(value) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
const cloned = new value.constructor(value.source, value.flags);
cloned.lastIndex = value.lastIndex;
return cloned;
}
function cloneBuffer(value) {
const length = value.length;
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const buffer = Buffer.allocUnsafe ? Buffer.allocUnsafe(length) : Buffer.from(length);
value.copy(buffer);
return buffer;
}
// eslint-disable-next-line @typescript-eslint/unbound-method
const valueOf = Symbol.prototype.valueOf;
function cloneSymbol(value) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return valueOf ? Object(valueOf.call(value)) : {};
}