// tslint:disable:no-any export function getPathValue(source: any, path: string): any { if (!path) { return source; } const parts: string[] = path.split('.'); let current: any = source; for (let i: number = 0; i < parts.length; i++) { if (current === undefined || current === null) { return undefined; } current = current[parts[i]]; } return current; } export function setPathValue(target: any, path: string, value: any): void { const parts: string[] = path.split('.'); let current: any = target; for (let i: number = 0; i < parts.length - 1; i++) { if (!current[parts[i]] || typeof current[parts[i]] !== 'object') { current[parts[i]] = {}; } current = current[parts[i]]; } current[parts[parts.length - 1]] = value; } export function cloneValue(value: T): T { return JSON.parse(JSON.stringify(value)); } export function mergePreservingUnknown(original: any, edited: any): any { if (!isObject(original) || !isObject(edited)) { return cloneValue(edited); } const result: any = cloneValue(original); Object.keys(edited).forEach((key: string): void => { result[key] = isObject(result[key]) && isObject(edited[key]) ? mergePreservingUnknown(result[key], edited[key]) : cloneValue(edited[key]); }); return result; } export function isEmptyValue(value: any): boolean { return value === undefined || value === null || value === '' || (Array.isArray(value) && value.length === 0); } function isObject(value: any): boolean { return !!value && typeof value === 'object' && !Array.isArray(value); }