/** * Immutably sets a value inside an object. Like `lodash#set`, but returning a * new object. Treats nullish initial values as empty objects. Clones any * nested objects. Supports arrays, too. * Duplicated from `packages/global-styles-engine/src/utils/object.ts` * * @param object Object to set a value in. * @param path Path in the object to modify. * @param value New value to set. * @return Cloned object with the new value set. */ export function setImmutably( object: Object, path: string | number | ( string | number )[], value: any ) { // Normalize path path = Array.isArray( path ) ? [ ...path ] : [ path ]; // Shallowly clone the base of the object object = Array.isArray( object ) ? [ ...object ] : { ...object }; const leaf = path.pop(); // Traverse object from root to leaf, shallowly cloning at each level let prev = object; for ( const key of path ) { // @ts-expect-error const lvl = prev[ key ]; // @ts-expect-error prev = prev[ key ] = Array.isArray( lvl ) ? [ ...lvl ] : { ...lvl }; } // @ts-expect-error prev[ leaf ] = value; return object; }