DEV Community

Cover image for Optional Chaining Has Arrived!
Laurie
Laurie

Posted on

Optional Chaining Has Arrived!

Last week we talked about Nullish Coalescing, now it's time for another new addition to ECMAScript.

The dreaded existence check

Have you ever worked with an API full of objects that were inconsistently formed? Multiple levels deep and frustrating to parse. Let's use a smaller example to talk about this.

const obj = {
  node : {
    thing: 1
  }
}
Enter fullscreen mode Exit fullscreen mode

Suppose we want to access thing. We can do it like this.

const thing = obj.node.thing
Enter fullscreen mode Exit fullscreen mode

But what if we can't guarantee that node exists? If we try and access thing on undefined we'll trigger an error. So we'll have to check first.

const thing = obj.node ? obj.node.thing : undefined
Enter fullscreen mode Exit fullscreen mode

This is the terser option, using a ternary, but it works all the same.

This is a reasonable piece of code! But it can get incredibly repetitive if you have deeply nested objects.

Optional Chaining to the Rescue

Well, we don't have to do that anymore. We can use the new optional chaining syntax.

const thing = obj.node?.thing
Enter fullscreen mode Exit fullscreen mode

In this case, obj.node is undefined. Typically, trying to access thing on undefined would trigger an error, but not in this case! When you use optional chaining it doesn't throw that error and instead evaluates the expression to undefined.

And what's even cooler is that we can combine this with nullish coalescing.

const obj = {}

const thing = obj.node?.thing ?? 2
// thing will be 2
Enter fullscreen mode Exit fullscreen mode

Since using optional chaining gives us undefined, thing will resolve to the value on the right-hand side of the ?? operator. In this case, that's 2.

Chaining Optional Chaining

Note that my example above uses optional chaining once in order to clarify how it works. However, you can use it multiple times in the same expression.

const thing = obj?.node?.thing
Enter fullscreen mode Exit fullscreen mode

The expression above is valid and may come in handy if obj looks like this.

const obj = null
Enter fullscreen mode Exit fullscreen mode

The risks

Now I can't write about optional chaining without including a section on warnings. To be honest, a lot of people were really against adding this to the language. They had concerns about abuse, and that's fair!

?. should NOT replace all instances of .. If you do that you'll create all kinds of silent failures. Optional chaining is another tool in your belt, that's it.

If you don't control the data you're accessing and it's particularly nested and it's ok if the result doesn't exist then maybe optional chaining is the right choice! But notice all those "and"s in the previous run-on sentence. Make sure you explicitly choose to use this syntax. It shouldn't be your default.

Not just for objects!

Oh, I forgot to mention the best part. Optional chaining works on more than just objects!

It works on arrays.

const tenthItem = arr?.[10]
Enter fullscreen mode Exit fullscreen mode

This makes sure that arr exists before trying to access the 10th element.

It works for function calls.

const message = obj?.stringFunction()
Enter fullscreen mode Exit fullscreen mode

This makes sure obj exists before you try and call a function on it.

And it works with top-level objects.

functionDoesNotExist?.()
Enter fullscreen mode Exit fullscreen mode

If this function doesn't exist, it will evaluate to undefined.

Isn't this fun?

So much power! But remember, that means you have a responsibility to use it wisely!

Oldest comments (35)

Collapse
 
ben profile image
Ben Halpern

I feel like optional chaining is a real love-hate programming language concept in general because of how it can be used to excuse poorly constructed programs.

Which makes it right at home in JavaScript 😄

Collapse
 
laurieontech profile image
Laurie

Lol, you're not wrong. There is a reason I couldn't write this post without a risks section!

Collapse
 
fly profile image
joon

I thought everything about JS is love-hate. :)

Collapse
 
gypsydave5 profile image
David Wickes
functionDoesNotExist?.()

😞😖😩😫😵

Collapse
 
vedmant profile image
Vedmant

This is certainly a good feature, before this I had to use something like lodash get('obj.node.foo', 'default').

Collapse
 
jakenherman profile image
Jaken Herman

Sweeeet

Collapse
 
jacobmgevans profile image
Jacob Evans

What do you need to enable it? Just some Babel stuff?

Collapse
 
jacobmgevans profile image
Jacob Evans

Nullish too?

Collapse
 
laurieontech profile image
Laurie

Ya, right now the only way to get the features is Babel. It will be in node soon, but no official announced date.

Thread Thread
 
jacobmgevans profile image
Jacob Evans

Wicked cool!

I also didn't know you could use it on arrays and functions which opens up a whole new world... I don't know how many times I've checked an array to exist and have length before using .map() 😆😅

Collapse
 
seanmclem profile image
Seanmclem

If you're a fan of react it's now part of react scripts 3.3. And in the latest version of vs code it's supported

Collapse
 
codenutt profile image
Jared

One of my favorite features in Swift/Kotlin, glad it's coming to my real home in JS haha

Collapse
 
ashvin777 profile image
Ashvin Kumar Suthar

Hi @Lauri, Nice article !!

Please try JSitor.com editor, it supports Nulliesh Coelscing and Optional Chaining already 😊

Collapse
 
itsjzt profile image
Saurabh Sharma

I'm waiting for the pipeline operator it will be the biggest change for me since es6

Collapse
 
devusman profile image
Usman Suleiman

I read somewhere that it could increase bundle size. How true is that?

Collapse
 
laurieontech profile image
Laurie

bundle size of node? Or the project that implements it?

Collapse
 
devusman profile image
Usman Suleiman

The project that implements it.

Thread Thread
 
laurieontech profile image
Laurie

It’s not really been in the wild enough to know. My suspicion is it isn’t a problem if you’re using it as a replacement for existence checks would have anyway. If you put it everywhere then yes, because the implementation is more complex than just accessing things.

Collapse
 
tylerlwsmith profile image
Tyler Smith

This is witchcraft and I love it 😂

Some comments may only be visible to logged-in visitors. Sign in to view all comments.