Skip to content

Instantly share code, notes, and snippets.

@kendallroth
Created January 20, 2022 23:14
Show Gist options
  • Save kendallroth/1f5afca32334dc395933c921ddd1fbe9 to your computer and use it in GitHub Desktop.
Save kendallroth/1f5afca32334dc395933c921ddd1fbe9 to your computer and use it in GitHub Desktop.
Update value in nested objects (with/without mutation)
/**
* Dynamically sets a deeply nested value in an object (returns new object)
*
* NOTE: By default it will create any missing nested keys!
*
* @param obj - Object which contains the value to set
* @param path - Path to nested key being set
* @param value - Target value to set
* @param recursive - Whether to create non-existing paths
* @returns Updated nested object
*/
const setDeep = (
obj: Record<string, any> = {},
[first, ...rest]: string[],
value: any,
recursive = true,
): Record<string, any> => {
// Optional prevent creating recursive keys if path is invalid/missing
if (!recursive && typeof obj[first] === "undefined") return obj;
// Arrays are currently not supported (will ignore)
if (Array.isArray(obj[first])) return obj;
return {
...obj,
[first]: rest.length ? setDeep(obj[first], rest, value, recursive) : value,
};
};
/**
* Dynamically sets a deeply nested value in an object (mutates input).
*
* By default it will create any missing nested keys!
*
* @param obj - Object which contains the value to set
* @param path - Path to nested key being set
* @param value - Target value to set
* @param recursive - Whether to create non-existing paths
*/
const mutateDeep = (
obj: Record<string, any>,
path: string[],
value: any,
recursive = true,
): void => {
let subObject = obj;
path.forEach((key, idx) => {
// Subobject will only be undefined when previous key did not exist
// and was not created (non-recursive call).
if (!subObject) return;
const isLastKey = idx === path.length - 1;
const isDefined = typeof subObject[key] !== "undefined";
if (isLastKey) {
subObject[key] = value;
} else if (!isDefined && recursive) {
subObject[key] = {};
}
subObject = subObject[key];
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment