Optional Chaining in JavaScript

I was just reading about the Babel 7 release, when I stumbled upon Optional Chaining and I got so excited, I thought I would quickly write a short post about it.

Optional chaining is basically a piece of syntactic sugar, which allows you to optionally chain properties and function calls, depending on the existence of the intermediate properties:

const nameError = errors && errors.address && errors.address.name
// turns into
const nameError = errors?.address?.name

A lot more readable, isn't it?

And here's the best thing: it is available in Babel in the plugin babel-plugin-transform-optional-chaining and even better, as announced in a blog post earlier this week will be added to Babel's stage-1 preset in version 7!

Flavours of Optional Chaining

As you've already seen, you can access properties of an object using optional chaining:

a?.b // a == null ? undefined : a.b

This also works if .b is a function:

a?.b() // a == null ? undefined : a.b()

You can also use it to access dynamic properties i.e. obj[propertyName]:

a?.[x] // a == null ? undefined : a[x]

And another really cool thing, you can even use it to invoke functions directly on the object you are checking:

a?.() // a == null ? undefined : a()

2 Examples using React

Since I am using React a lot and because of it's general popularity within the JS community, I'll just quickly share two examples of how you'll be able to use this new piece of syntactic sugar in real-live examples:

The most obvious usecase is probably to access optional props. For example to call an optional, passed-down function:

onClick = evt => {
    // do something with evt
    this.props.onClick?.(evt) // call onClick if defined
}

Similarly, think of accessing values inside nested structures, for example in the context of a form. The following form-field is part of a user form, which has a nested user.address. We can use optional chaining both for passing down errors and values to the Input component:

<Input
    label="Street Name"
    error={this.props.errors?.address?.streetName}
    value={this.props.user?.address?.streetName || ''}
    required
/>

You get the idea :)


Hope you could take away something useful from this short post.

You can read more about the TC39 proposal here: https://github.com/tc39/proposal-optional-chaining

And about the upcoming version of Babel here: https://babeljs.io/blog/2017/09/12/planning-for-7.0

Share article