const get = (t, path) =>
path.split(".").reduce((r, k) => r?.[k], t)
const set = (t, path, value) => {
if (path == "") return value
const [k, next] = path.split({
[Symbol.split](s) {
const i = s.indexOf(".")
return i == -1 ? [s, ""] : [s.slice(0, i), s.slice(i + 1)]
}
})
if (t !== undefined && typeof t !== "object")
throw Error(`cannot set property ${k} of ${typeof t}`)
return Object.assign(
t ?? (/^\d+$/.test(k) ? [] : {}),
{ [k]: set(t?.[k], next, value) },
)
}
// build data from previous example
const mydata = set({}, "a.b", [
b.0,
set({}, "c.c.d", ["hello", "world"])
])
// print checkpoint
console.log(JSON.stringify(mydata, null, 2))
// set additional fields
set(mydata, "a.b.1.c.d.1", "moon")
set(mydata, "a.b.1.w", "x.y.z")
// ensure changes
console.log(JSON.stringify(mydata, null, 2))
.as-console-wrapper { min-height: 100%; top: 0; }