Implement unsquashObject(flat) — the inverse of squash-object. You're given a single-level object whose keys are dot-delimited paths, and you rebuild the nested object they describe. unsquashObject({ 'a.b': 1 }) becomes { a: { b: 1 } }. Think of it as turning a flat list of full file paths back into a folder tree: docs/notes/todo.txt becomes a docs folder containing a notes folder containing todo.txt. This is the expansion that config loaders and form libraries do to turn a flat user.address.city key back into a real nested shape. Keep it symmetric with squashObject so a round-trip is lossless.
// flat: a single-level object. Every key is a dot-joined path string;
// every value is a LEAF — a primitive, null, an array, or an object,
// kept exactly as-is (never re-split or recursed into).
// returns: a new nested object whose structure is described by the dotted keys.
function unsquashObject(flat): Record<string, unknown>;
// One dotted key becomes one level of nesting.
unsquashObject({ 'a.b': 1 });
// → { a: { b: 1 } }
// A deep path, a shorter path that shares its prefix, and a flat key.
unsquashObject({ 'a.b.c': 1, 'a.d': 2, e: 3 });
// → { a: { b: { c: 1 }, d: 2 }, e: 3 }
// Leaves are stored as-is — an array is never treated as a branch.
unsquashObject({ 'tags': ['x', 'y'], 'meta.author': null });
// → { tags: ['x', 'y'], meta: { author: null } }
. and walk the path. For every entry, break the key into segments. Every segment except the last names an intermediate object to step into (creating it if it isn't there yet); the last segment names where the value lands.{ e: 3 } has a one-segment path, so it becomes { e: 3 } — no nesting.{ 'a.b': 1, 'a.c': 2 } builds a single a object holding both b and c. The second key must reuse the a you already created, not clobber it.null, an object, or a primitive is set verbatim at the final segment. Don't recurse into it; don't re-split its own keys on dots. This mirrors squashObject's leaf rule so the two round-trip cleanly.{ a: 1, 'a.b': 2 } — the key that comes later decides. Here 'a.b' overwrites the leaf 1, giving { a: { b: 2 } }. Reverse the order and the later leaf wins instead.flat; build and return a fresh nested object.