export function dottedGet(obj: any, path: string): any { const nodes = path.split(/\./g); return nodes.reduce((a, c) => { const index = dotgetkey(a, c, false); return a ? a[index] : undefined; }, obj); } export function dottedSet(obj: any, path: string, value: any): void { let current = obj; const keys = path.split(/\./g); for (let i = 0; i < keys.length; i += 1) { const next = keys[i + 1]; const index = dotgetkey(current, keys[i], true, next); if (i === keys.length - 1) { current[index] = value; } else { current = current[index]; } } } function dotgetkey( current: any, key: string, mutate = false, next?: string, ): string | number { const index = parseFloat(key); let indexKey: string | number = key; if (index || index === 0) { indexKey = index; if (mutate && index === current.length) { current.push({}); } else if (index < 0 || index >= current.length) { throw new Error(`Index out of range: ${index}`); } } else if (mutate && current[key] === undefined) { if (next) { const index = parseFloat(next); if (index || index === 0) { current[key] = []; } else { current[key] = {}; } } else { current[key] = {}; } } return indexKey; } export default dottedGet;