DEV Community

Sam Holmes
Sam Holmes

Posted on

5 2

Optional Chaining in JavaScript Right Now!

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!

Sentry blog image

Identify what makes your TTFB high so you can fix it

In the past few years in the web dev world, we’ve seen a significant push towards rendering our websites on the server. Doing so is better for SEO and performs better on low-powered devices, but one thing we had to sacrifice is TTFB.

Read more

Top comments (5)

Collapse
 
karataev profile image
Eugene Karataev

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
Collapse
 
samholmes profile image
Sam Holmes

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.

Collapse
 
jasonbarry profile image
Jason Barry

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.

Collapse
 
samholmes profile image
Sam Holmes

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

Collapse
 
ashvin777 profile image
Ashvin Kumar Suthar • Edited

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

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs