loading...

Optional Chaining in JavaScript Right Now!

samholmes profile image Sam Holmes ・2 min read

In case you don't know what Optional Chaining is, it's the ability to safely access properties of a variable without a reference error.

var obj = undefined
obj?.foo // Returns undefined without throwing an error

This is an experimental JavaScript feature proposal, however, we can use a form of this feature today with the help of the a Proxy object!

Let's define a function which will return a special Proxy object which will prevent references on undefined values allowing us to safely query for properties.

function safe(value){
    return new Proxy({}, {
        get: (_, prop) => {
            if (prop === 'unsafe')
                return value
            else if (value && typeof value[prop] !== 'undefined')
                return safe(value[prop])
            else
                return safe(undefined)
        }
    })
}

Now we can use this function as an alternative to the Optional Chaining Operator like so:

var obj1 = undefined
var obj2 = {foo:23}

console.log(safe(obj1).foo.unsafe) // Returns undefined without throwing an error
console.log(safe(obj2).foo.unsafe) // Returns 23
console.log(safe(obj2).foo.bar.baz.unsafe) // Returns undefined

There is a con to this approach in that unsafe becomes a reserved property within the chain. Though, we can implement a second parameter to the safe function to take care of this edge case:

function safe(value, unsafe = 'unsafe'){
    return new Proxy({}, {
        get: (_, prop) => {
            if (prop === unsafe)
                return value
            else if (value && typeof value[prop] !== 'undefined')
                return safe(value[prop])
            else
                return safe(undefined)
        }
    })
}

That's all for now. Let me know in the comments what you think of this pattern.

I've open sourced this idea as an NPM package: safeunsafe

Cheers!

Posted on by:

samholmes profile

Sam Holmes

@samholmes

Passionate Sourcerer of the Web and JavaScript

Discussion

pic
Editor guide
 

This is a clever use of Proxy to safely access object properties ✨

What do you think about lodash way to get object properties? It solves the same problem, but in different way.

var obj = {foo: {bar: 'baz'}};
_.get(obj, 'foo.bar'); // baz
_.get(obj, 'lol.kek'); // undefined
 

This approach is reasonable. It comes down to style really. Using Proxies allows you to tap into some meta-programming aspects of JavaScript where you can change the behavior or the syntax slightly. Either way you accomplish this is fine, however Proxies seems like a nicer use case.

 

I'd lean on the @babel/plugin-proposal-optional-ch... plugin instead – seems a bit safer. Although your method is clever and could be a quick way to get optional chaining if you don't currently have a transpilation step.

 

Yes! This is a solution where you may not be using babel or some other transpiler.

 

You can now try optional chaining in JSitor online editor to test it out.