How to check successive object presence elegantly

Viewed 107

Is there any way to write this more elegantly?

if ("a" in obj && "b" in obj.a && "c" in obj.a.b)

instead of checking for existence on each stage of the object?

If I do if ("c" in obj.a.b) this will give error if a or b doesn't exist.

3 Answers

I've always found the lodash _.has and _.get functions very powerful, you can access deeply nested values in objects without a lot of code to check the path exists.

For example:

const obj = { a: { b: { c: 42 }}};

if (_.has(obj, "a.b.c")) {
    console.log("Path exists");
}

// Safe to access, will return undefined if path does not exist...
console.log("Path value:", _.get(obj, "a.b.c"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>

pluckDeep helper function

function pluckDeep(key) {

   return function(obj) {

        return key.split('.').reduce((accum, key) => {
            return accum[key]
        }, obj);

   }

}

const obj = { a: { b: { c: 42 }}};


if (pluckDeep('a.b.c')(obj)) {
  // do something
}

This curried function can determine if a property exist by using the first parameter of the pluckDeep function.

Old way

if (obj.a && obj.a.b && obj.a.b.c) {
  // do something
}

New way

Optional chaining

if (obj.a?.b?.c) {
  // do something
}
Related