DEV Community

Sammy Israwi
Sammy Israwi

Posted on • Updated on

Optional Chaining may be coming to JavaScript

Update: Optional Chaining is finally in Stage 4!! Which means it is part of the ES2020 specification. It has also already made it to TypeScript v3.7.

Here's the repo with all the info you need.

What is it?

Optional Chaining allows us to check if an object exists before trying to access its properties. Some other languages have something similar. C#, for example, has a Null Conditional Operator that behaves very similarly as the proposed Optional Chaining.

Why do we need it?

Have you ever had to check for the existence of objects or arrays before accessing its properties? If you forget, it may look a little bit like this:

if(specimen && specimen.arms && specimen.arms.length > 2)
    console.log("This is probably an alien");
Enter fullscreen mode Exit fullscreen mode

The reason why we do these checks is because in JavaScript allows for anonymous objects that don't necessarily have a structure or schema. Therefore if we don't check for parents in an object tree, we get a lot of errors that look like this:

TypeError error message

Because, at least in the case of the error, specimen does exist, but it does not have an arms property. Therefore, we tried to get length of something that was undefined.

So, what's the proposal?

Instead of all that, we can chain optional checks like this:

if(specimen?.arms?.length > 2)
    console.log("This is probably an alien");
Enter fullscreen mode Exit fullscreen mode

However, keep in mind that the Optional Chaining operator is ?. not ? - this means that when using it to access an item in an array, it will look like this instead:

var firstArm = specimen?.arms?.[0]; //CORRECT
var secondArm = specimen?.arms?[1]; //WRONG
Enter fullscreen mode Exit fullscreen mode

Similarly, when using it to check for the existence of functions:

var kickPromise = specimen?.kick?.();  //CORRECT
var punchPromise = specimen?.punch?(); //WRONG

Enter fullscreen mode Exit fullscreen mode

In this case, we check if kick exists before calling it as a function!

How does it work?

The operator checks if whatever is to the Left-Hand Side of ?. is null or undefined. If it is, then the expression short-circuits and returns undefined. Otherwise, the expression continues to evaluate as if nothing is wrong.

When can I use it?

Well, it is still a proposal so it's not in Vanilla JavaScript just yet. However, it is usable with Babel!

To stay up to date with the status of the proposal, as well as to have a more in-depth understanding and to check some examples, you should check their GitHub repo! You can also find the specs here, but I won't get into that since most of that document goes way over my head 😅

Thank you!

You're welcome! ❤️

Oldest comments (41)

Collapse
 
ben profile image
Ben Halpern

Wooo fun!

Collapse
 
denvercoder profile image
Tim Myers

JS is looking more like Swift every day. 👍

Collapse
 
twof profile image
Alex Reilly

Swift masterrace

Collapse
 
leebradley profile image
Leopold Bradley

Very useful feature, and better than including lodash get in my code. Although, hasn't the optional chaining operator has been in Stage 1 for a while? Is there something to indicate this feature is moving up in the world?

Collapse
 
sammyisa profile image
Sammy Israwi

Yeah, it has been in Stage 1 for a long while. From what I can gather in these meeting notes from last year there is still no consensus on the exact syntax, and some people are still discussing the scope of the proposal.

Short version is, function call ?.() and bracket access ?.[n] parts are not loved because the syntax. The three operators ?., ?.(, and ?.[ don't do the exact same thing, so it leads to confusion.

I'd say the fact that there is an active discussion about this feature in the TC39 meetings indicate that this feature is moving up - but to be honest I could be wrong. I'm only slightly familiar with the process.

Collapse
 
wahabshah23 profile image
Abdul Wahab Shah

Typescript already has this. Would be nice in vanilla Js too

Collapse
 
neoscrib profile image
Tanner Jepsen

Typescript does not have it. They won't implement anything in stage 1. github.com/Microsoft/TypeScript/is...

Collapse
 
evanderwpmorais profile image
Evander

I have used it in Angular isn't it Typescript?

Thread Thread
 
cristianfalcone profile image
Cristian Falcone

That's from Angular template syntax. It's called safe navigation operator. Not from TypeScript.

Collapse
 
sammyisa profile image
Sammy Israwi • Edited

So apparently there has been a lengthy, 3 years long discussion about adding this to TS, which sometimes gets heated.

But it seems from the last comment on the thread that it actually has not been implemented in TypeScript, and it wont be implemented until the ES committee locks down its semantics :/ That is, unless there's something I'm missing?

Collapse
 
rapasoft profile image
Pavol Rajzak

It is present in CoffeeScript

Collapse
 
caubeen profile image
caubeen

Wow this is awesome. I've wanted this forever. The next thing I would want is this for arbitrary conditionals such as findIndex. If findIndex returns -1 consider it errored.

Collapse
 
buinauskas profile image
Evaldas Buinauskas

Didn't know this exists in c#! Neat

Collapse
 
kjellski profile image
Kjell Otto

C# is awsome, have a look here: docs.microsoft.com/en-us/dotnet/cs...
There is also async await for years now... ;)

Collapse
 
buinauskas profile image
Evaldas Buinauskas

I'm a beginner in C# and recently I've had to make null check nested fields and now knowing chaining operators, it's much easier and simplifies my code :)

Collapse
 
sammyisa profile image
Sammy Israwi

C# is a fantastic language :D

Collapse
 
briansotodo profile image
b

I don't know about the syntax (func?.() and arr?.[0] is kind of weird) but it would be really useful!

Collapse
 
sammyisa profile image
Sammy Israwi

Yeah, you are not alone in that. That syntax of those seems to be the main reason this is still in Stage 1. It's likely that will change before hitting Stage 2!

Collapse
 
t4rzsan profile image
Jakob Christensen

In C# it is also called the Elvis-operator because it looks a bit like two eyes under curvy hair.

Collapse
 
briankephart profile image
Brian Kephart

Nice. I've just started using similar methods in Ruby to make my code cleaner, so it will be nice to use this pattern in JS too.

Collapse
 
mladenstojanovic profile image
Mladen Stojanovic

Wow! Can't wait for this one!

Collapse
 
pomax profile image
Mike Kamermans • Edited

How fixed is this syntax? Because while it's in draft and there is still a possibility of changing it: this is quite painful syntax, a keyword that turns an entire statement into a "is allowed to fail due to 'X does not exist' errors" would be so much nicer to work with. For instance, ... if exists [else ...] would allow for pleasant to read, easy to type expressions such as let value = ... if exist and if (... if exists else Number.MAX_VALUE > 2). This would be so much better, and would still be guaranteed to not conflict with existing code (since if cannot be followed by anything except ( right now), and can be trivially dealt with by transpilers for targeting legacy systems.

Collapse
 
sammyisa profile image
Sammy Israwi

While the exact syntax is not written in stone yet (in fact, it's subject of much debate) I'd say it's not fixed at all. However, what you're describing seems to be a different feature that fixes a different problem.

They may have some overlap in the sense that they try to change how we act on null or undefined references, but they both approach it in very different ways.

Collapse
 
irvandoval profile image
Irvin Sandoval • Edited

It will be an amazing and very useful feature 🤓

Collapse
 
inf3rno profile image
inf3rno

Great work on worsening readability of js code day by day. :S

Collapse
 
sammyisa profile image
Sammy Israwi

Why do you think so? I agree that the syntax right now is not great, and that it needs some tweaking. But overall it seems like a nice Quality Of Life improvement on the language.

Collapse
 
inf3rno profile image
inf3rno • Edited

You might be right. I just watch it from a different perspective than you. I would write if(specimen instanceof Alien) where you write if(specimen && specimen.arms && specimen.arms.length > 2). But I can accept that many devs are working with structured code, so this new feature will be fine for them. I might use it rarely too by processing nested config objects.

Collapse
 
anthonybrown profile image
Tony Brown

Me likey

Collapse
 
pat_metzdorf profile image
Patrick Metzdorf

The syntax really needs to change, though.

Something like

foo.?bar?[baz] or foo.bar?[baz]? (i.e. question mark right before or after the property that may be undefined)

would be much more intuitive imho.