UNPKG

vlens

Version:

Data Centric Routing & Rendering Mini-Framework

106 lines (100 loc) 3.13 kB
/** * Clone a value deeply if it's an object or array. * @param value the value to be cloned * @param key optional - indicates the key where this value was present in the parent object, if applicable * @returns a clone of value */ export function deepCloneValue<T>(value: T, key?: string): T { switch (typeof value) { case 'object': if (Array.isArray(value)) { // @ts-ignore return deepCloneArray(value); } else if (value === null) { // @ts-ignore return null; } else { // @ts-ignore return deepCloneObject(value); } case 'number': case 'bigint': case 'string': case 'symbol': case 'boolean': return value case 'function': if (key) { console.warn('deepCloneValue encountered a function value at', key) } else { console.warn('deepCloneValue encountered a function value!') } return value; case 'undefined': return value; } throw "unreachable" } export function deepCloneArray(data: unknown[]): typeof data { return data.map(v => deepCloneValue(v)) } export function deepCloneObject<T extends object>(data: T): T { // @ts-ignore let clone: T = {}; for (const [key, value] of Object.entries(data)) { // @ts-ignore clone[key] = deepCloneValue(value, key); } return clone; } export function isValueDifferent(value1: unknown, value2: unknown): boolean { if (typeof value1 !== typeof value2) { return true; } switch (typeof value1) { case 'number': case 'bigint': case 'string': case 'symbol': case 'boolean': return value1 !== value2; case 'object': if (Array.isArray(value1) && Array.isArray(value2)) { return isArrayDifferent(value1, value2); } else if (!Array.isArray(value1) && !Array.isArray(value2)) { // @ts-ignore return isObjectDifferent(value1, value2); } else { // one is array and one is object return true; } case 'function': return value1 !== value2; case 'undefined': return false; } } export function isArrayDifferent(value1: unknown[], value2: unknown[]): boolean { if (value1.length !== value2.length) { return true; } for (let index = 0; index < value1.length; index++) { if (isValueDifferent(value1[index], value2[index])) { return true; } } return false; } export function isObjectDifferent<T extends object>(data1: T, data2: T): boolean { for (const [key, value1] of Object.entries(data1)) { if (!(key in data2)) { return true; } // @ts-ignore const value2 = data2[key]; if (isValueDifferent(value1, value2)) { return true; } } return false; }