You've got a deeply nested object — an API response, a config tree, a form-state blob — and you need to read a value buried inside it. Optional chaining (obj?.a?.b?.c) covers the static case, but when the path is data ('a.b.c' from a config file, a query string, a permission key), you need a function. Implement get(obj, path, defaultValue?) — the same shape lodash's _.get ships.
get walks the path one segment at a time and returns the value at the end. If any intermediate segment is missing — or if the final value is undefined — it returns defaultValue instead. Critically, null is a real value; only undefined triggers the default.
get(
obj: unknown, // root object or array
path: string | (string | number)[], // 'a.b[0].c' OR ['a', 'b', 0, 'c']
defaultValue?: unknown // returned when missing or undefined
): unknown
// basic dot path
get({ a: { b: 1 } }, 'a.b');
// → 1
// missing path with default
get({ a: { b: 1 } }, 'a.c.d', 'fallback');
// → 'fallback'
// bracket index into an array
get({ users: [{ name: 'Ana' }, { name: 'Bob' }] }, 'users[1].name');
// → 'Bob'
// array path — escape hatch for keys with special chars
get({ 'a.b': { c: 7 } }, ['a.b', 'c']);
// → 7
// null is a real value — NOT replaced by default
get({ a: { b: null } }, 'a.b', 'fallback');
// → null
'a.b[0].c') and array (['a', 'b', 0, 'c']) forms. Bracket notation [n] reads array indices; dots separate object keys.defaultValue only when the resolved value is strictly undefined OR when an intermediate segment can't be accessed (null/undefined parent). A leaf that's null, 0, '', or false is a real value — return it as-is.null.foo must NOT throw a TypeError. Detect the dead end and return defaultValue.'a.b' as a single key) can't be expressed in string form. That's why the array path exists.'a\\.b'), function calls in paths, or assignment. Read-only access is the whole API.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.