DEV Community

Cover image for 😲🤯The most outstanding new feature in Javascript you need to know about: Optional Chaining

😲🤯The most outstanding new feature in Javascript you need to know about: Optional Chaining

Michael "lampe" Lazarski on September 15, 2019

Optional chaining is a game-changer for everybody how is working with Javascript. It is as essential as Fat Arrow Functions or 'let' and 'const'. L...
Collapse
 
chrisachard profile image
Chris Achard

YES! I've been super excited waiting for this in javascript since ruby added it in 2.3.

It's certainly a lot better than writing:

const x = this.props.data && this.props.data.myObject && .....

:)

Thanks for the pointer to the babel plugin!

Collapse
 
qm3ster profile image
Mihail Malo

Is there any issue in Ruby with people overusing this feature and it becoming unclear what is nullable and what isn't?

Collapse
 
chrisachard profile image
Chris Achard

I think it can if you overdo it, yes (there are a few blogposts about that if you search for them) - but in general, for patterns like checking if a prop exists, etc, I think it's a good thing.

There might be an argument for: "if you need to do that regularly, then maybe you need a different abstraction or way of doing things"... but I haven't thought too much about that, so I'm not sure.

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

I would say that the objects you are getting are not well designed.

If you need to check that often that it will be a problem.

I mean you can overdo everything, adding 200 npm packages even if they just do small things would also be a bad pattern. In the end, it is in your fingertips to decide.

Thread Thread
 
chrisachard profile image
Chris Achard

Right, yep - if you're constantly checking the same thing for null or not, then maybe you need to abstract that to give you a better framework/way to access it.

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

Like always thinking is the key here 😉

Thread Thread
 
qm3ster profile image
Mihail Malo • Edited

IMO it lends itself to patterns like:

useWidth(this.props.data?.myObject?.width||100)
alsoUseWidth(this.props.data?.myObject?.width||222)

Not only are you doing extra branching, but by having defaults at the usage site instead of defaults site you could have inconsistencies.

Instead, on construction of the this, you could have

this.data=_.merge(defaultData, incomingData)

and then access all the properties unconditionally.
(You could also only merge in properties that already exist in defaultData tree, and perform validation at this stage, creating a very predictable this)

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Exactly!

It is just way easier to write :)

No problem.

In general proposal usually, have babel plugins. It just sometimes hard to find them or you have to directly search for them :)

Collapse
 
devdrake0 profile image
Si

It's probably worth mentioning that TypeScript don't have support for this feature yet (AFAIK), so could lead to some IDE 'errors'.

There is also no plugin to add them into TS support syntax checking yet, so we have to live with the errors or disable TS checks.

Collapse
 
lorenzhenk profile image
Lorenz Henk

They plan to add it in TS 3.7.0! 😁

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Nice I really need to try TS at some point :)

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Thanks for mentioning this!

I don't work with TS that often but I think at some point they will support it :)

does TS support babeljs? if yes maybe they can work together right now? 🤔

Collapse
 
devdrake0 profile image
Si

Neither do I but it's what drives the syntax support in Visual Studio Code :)

So, even when just working with JavaScript, you may still get errors in VSC - even though it will run absolutely fine. It can throw some red herrings for devs who aren't aware why, so just thought I'd mention it.

Not for what I'm talking about, no. Whether TS and Babel can work, when writing TS, is a question for someone that uses TS :)

I'm referring to the VSC built-in JS/TS validator. It can be disabled by updating the settings.json file to include "javascript.validate.enable": false and/or "typescript.validate.enable": false. If they are disabled ESLint can take over and show the appropriate errors.

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

Ahh okay yeah, that's true!

VSC will show an error if you don't configure it!

I just got used to seeing the error 🤣

Collapse
 
sent2null profile image
David Saintloth

I'm pretty sure typescript has something like this ... I know because my last angular project came to a point where I used the ? in a way similar to this to disambiguate values extracted from defined types in the app. Nothing major (it was my first project) but I definitely remember finding usage of "?" as a means of testing type attributes without using a long if condition with explicit null checking. I'll have to confirm by looking at my project code.

Thread Thread
 
devdrake0 profile image
Si

Are you maybe referring to Ternary operators?

Thread Thread
 
sent2null profile image
David Saintloth

Interestingly enough today at work I opened up the project in question and was unable to find where I used the "?" in the typescript. I think it may have been in an html file using an ng directive but had to switch off to other work before I finalized my search.

You could be right...I'll confirm again tomorrow.

Collapse
 
marcellothearcane profile image
marcellothearcane

Why

const personFirstName = person?.details?.name?.firstName ?? 'stranger'

Rather than

const personFirstName = person?.details?.name?.firstName || 'stranger'

?

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Good question!
Example time!

const user = {
    auth: {
        isLoggedIn: false
    }
}

const isLoggedIn = user.auth?.isLoggedIn || true
// isLoggedIn would be true!

const isLoggedIn = user.auth?.isLoggedIn ?? true
// isLoggedIn would be false!

As you can see there is a difference in how they work.
The problem with || is that it will return the right value when the left value is falsy. The ?? just checks for null or undefined.

Collapse
 
joshsanger profile image
Joshua Sanger

Could also consider converting to a true/false value with:

const isLoggedIn = !!(user.auth?.isLoggedIn)
Thread Thread
 
thecodingalpaca profile image
Carlos Trapet

@joshua I was literally going to say the same thing.
I fail to see the point/usefulness of the '??' operator

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

There are always alternatives if you can also write

if(user.auth?.isLoggedIn === true){
    // user is logged in!
}

Nobody is forcing anybody to use the ?? operator but I think it just fits nicely together with the ?. and makes the intent clear if the developer knows how both of them work.

Collapse
 
sethjeffery profile image
Seth Jeffery

Probably that ?? only cares about undefined properties, not null or zero or empty string etc.

Collapse
 
mburszley profile image
Maximilian Burszley

It's called nullish for a reason. Because for some reason, JS thought two nulls would be a good idea.

Thread Thread
 
sethjeffery profile image
Seth Jeffery

May be a long argument but it's not two nulls, it's a null (defined) and an undefined. They have usefully different meanings and usages. Saying it's two nulls is a bit like saying that zero and null are the same because they both mean "nothing".

Thread Thread
 
jessyco profile image
Jessy

I would have to agree with you, however in the wild most code I've seen misinterprets this and there is mixed usage of both all over the place..

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

And everybody is true here :)

I try to use undefined as much as I can instead of null.

But some frameworks want you to use null.

Collapse
 
tanuj101 profile image
Tanuj Nagpal

No use until it is supported by major browsers

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Why not just use babel.js?

You as a developer don't even see the difference?

One day you will just remove the babel.js plugin and that's it.

Collapse
 
tanuj101 profile image
Tanuj Nagpal

Oh didn't see the plugin

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

there is a link in the Start using it today section.

babel-plugin-proposal-optional-cha...

Thread Thread
 
tanuj101 profile image
Tanuj Nagpal

yeah got it thanks!

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

No problem :)

Thread Thread
 
slashgear_ profile image
Antoine Caron

We should really consider not to use it until it is available in browsers.

The polyfill is really ugly and verbose.

That's why I wrote this article

dev.to/slashgear_/optional-chainin...

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

I have a confession to make.

I really really dislike lodash and underscore.

If you look at babel code,
in general, it does not look good.

Besides that looking at the lodash code it is not much better ;)

But that's just my opinion, there is no right or wrong here!

Thread Thread
 
mateiadrielrafael profile image
Matei Adriel

Totally agree:)

Collapse
 
fcfn profile image
Peter Timoshevsky

I used this ugly piece: (((foo || {}).bar || {}).baz || {}).xyz 🥺

Collapse
 
johnylab profile image
João Ferreira

wow! this is gold

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

This is a piece of art! 🤣

Collapse
 
clarity89 profile image
Alex K.

It's worth mentioning the Nullish coalescing together with optional chaining. They're at the same stage in tc39 proposals. Here's a really good in-depth explanation.

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

That's true and thanks for the info.

The goal was to make this a more beginner-friendly and for me, the proposal stages and the blog from axel are more for advanced developers but yeah his blog is always good to read 😃👍

Collapse
 
jussiry profile image
Jussi Rytkönen

One more feature directly copied from CoffeeScript 😅 Great language,shame so few use it anymore.

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

'Optional Chaining' Is also called 'Safe navigation operator' and is supported by a lot of languages. Like Ruby, Swift, Kotlin, Rust, .NET, Objective-c and more 😊

Finally, it is coming to Javascript!

Collapse
 
jussiry profile image
Jussi Rytkönen

True, it certainly wasn't invented by CoffeeScript. Just considering how many CS features ended up in JS, it was quite visionary to see what JS was lacking (fat arrow, destructuring, default arguments, etc). And this happened almost 10 years ago!

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

That's also true :)

But it also had some problems.

I remember the old good times sitting in an IRC channel and seeing CoffeeScript problems popping up all the time ;)

Thread Thread
 
jussiry profile image
Jussi Rytkönen

If you wanna take a trip down the memory lane check out my reactive editor where i still write most things in CS :D

edide.io/whirl_of_geometry

Of course it supports JS as well, but I just love CS so much i never gave up on it 😅

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

Haha, that's amazing!

I mean if it works for you why not 😀

Collapse
 
rpedroni profile image
Ricardo Pedroni

Remember using this in CoffeeScript in 2014 lol

Collapse
 
svitekpavel profile image
Pavel Svitek

This is probably the worst proposal ever. It will allow to write even shittier code in JS.

Rather than solving the problem by better code design, devs will use this crappy shit.

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Okay, why is this crappy?

What do you mean with better code design?

Please explain a little bit more what you mean.

Collapse
 
svitekpavel profile image
Pavel Svitek

You are retrieving some data from API. Till you retrieve the data, you should have something like data: null, after you get data from API, you should have the whole object.

API should always return you a predefined object structure, right? So once data !== null, you should be able to access all properties and deep properties instead of checking every object in your structure.

I understand that there might be some valid cases where object?.property?.property might be a shorter code, but it doesn't mean it should be implemented in the language.

Once this is in language, the syntax will be overused and more shitty code will be written.

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

What if the API is not in your hand and you have no control over it?

I don't see it being overused in ruby or c# or any other language. Why should this happen in JS?

Thread Thread
 
sudojoe profile image
Joseph Locke • Edited

Assuming that objects returned from third-parties conform to a specific structure (and therefore, not 'verifying' their structure and the presence/lack-thereof of expected properties) is most-likely a security blunder.

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

Sorry, I don't fully understand what you mean.

Collapse
 
thewix profile image
TheWix

A better pattern would be to use Option/Maybe or Either.

If I have something like:

var a = null;

rather than using a?.b I would use:

const a = fromNullable(a);

const aValue = a.map(_ => _.b).getOrElse("No value");

You can further chain like

a.chain(_ => .b)
.chain(
=> .c)
.chain(
=> _.d)

In your anti-corruption layer convert all nulls to Option/Maybe and you don't have to deal with nulls.

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

I would love to not deal with null/undefined in JS.

I find the ?. really elegant.

But I also find Ruby elegant where things like this are normal.

Collapse
 
mohamedelidrissi_98 profile image
Mohamed ELIDRISSI • Edited

Yay finally JavaScript is getting inspiration from Kotlin!

Edit: After seeing a few comments looks like this is already in a few other languages

Collapse
 
broderick profile image
Broderick Stadden

Kotlin is heavily inspired by C#. Which also influences TypeScript. I think the lesson is, C# does a lot right! I just wish there was a 1-to-1 implementation of LINQ in TypeScript 🥳

Collapse
 
sudojoe profile image
Joseph Locke

You can always create a C#/Node project and call it from JS :D

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Yeah, some other languages also have this!

and finally JS also will have it :)

Collapse
 
mohamedelidrissi_98 profile image
Mohamed ELIDRISSI

Sorry for the late reply. Also Nullish coalescing operator? Who makes these names? We should call it the elvis operator

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

Usually, they come from Math people 🤣🤣🤣

Thread Thread
 
mohamedelidrissi_98 profile image
Mohamed ELIDRISSI

No doubt

Collapse
 
carlillo profile image
Carlos Caballero

I think that the chaining operator is a patch when you're not satisfying the law of demeter.

My post about Demeter's law on Dev.to (dev.to/carlillo/demeters-law-dont-...).

What do you think about that?

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Yes, I'm on your side here!

the ?. is a patch around bad object and API design.

Having this deeply coupled and tightly integrated objects is never a good thing.

The problem is that you can not always control what data you are getting.

Another problem is that NoSQL databases promote deeply nested objects and then they don't provide any schema mechanisms. This was always a strange thing coming from SQL where Schemas were the norm.

But yeah nice article!

Collapse
 
carlillo profile image
Carlos Caballero

Thanks for your opinion 😊

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

Your welcome 😀👍

Collapse
 
ashvin777 profile image
Ashvin Kumar Suthar

Thanks, Iampewebdev for sharing this great article. And the great news I would like to share is, that you can actually use an online web dev tool which supports this feature. If anyone of you interested in trying out, check out this article or jump directly to code editor - jsitor.com/bIhQS-b4Y

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Nice!

I will try it out!

Thanks for the info :)

Collapse
 
ashvin777 profile image
Ashvin Kumar Suthar

Thanks.

Thread Thread
 
lampewebdev profile image
Michael "lampe" Lazarski

Your welcome 😀🙌

Collapse
 
devinrhode2 profile image
Devin Rhode

actually that lodash _.get methods looks pretty good.. could also have extra functionality to tell you which property was undefined, to help with debugging

and that lodash method COULD be added to the Object.prototype... so you COULD do..

person.lookup('details.name.fullName')

Maybe person is defined but is missing the details object. Maybe there's no fullName property. An actual function call could tell you these things in a very elegant want.

Collapse
 
michi profile image
Michael Z

I hope it won't be overused like destructuring. I can already see the linting rules that dictate you have to use this 100% when working with objects.

Collapse
 
georgecoldham profile image
George

Ooft, pet peeve right here.

When you need to use a single value that is passed in from an object and pass the whole object on.... No, props.value is fine, why am I being made to destructure and rebuild/copy my object just to use a single property.

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

There will be a phase where you see it everywhere like with spreading but after a short time it will lose its novelty and people will use it more when it's needed. 😀🙌

Collapse
 
kiransiluveru profile image
kirankumar

If anyone using Ramda library here we can use pathOr function which is like same optional chaining

But if this optional chaining is supported by default by javascript that would be better

Thanks @Iampewebdev

Collapse
 
michaelrodov profile image
Michael Rodov

FINALLY!!!! thank you man

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Your welcome!
Glad you liked it!

Collapse
 
aleduruy profile image
Alessandra Duruy

Wooah this is a really useful feature!! Thanks for sharing :D

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Your welcome :)

Collapse
 
ex_y profile image
Ashe • Edited

I can't wait to use this :)

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Me too!

It makes backend code so much easier :)

Collapse
 
bananabrann profile image
Lee

This is great! Thanks!

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Thank you!

Collapse
 
havespacesuit profile image
Eric Sundquist

C# has had this for several years. One of my favorite features. Can't wait to see it officially release in TypeScript!

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

And in Javascript ;)

Collapse
 
kdraypole profile image
Kobe Raypole

Reminds me of ruby’s Safe navigation operator

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Because it is the same idea just a different syntax.

Collapse
 
sagarb3 profile image
Sagar Bhattacharya

So now js is following the syntax of c#

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Yup it is and in this case, it is a good thing 😋

Collapse
 
polluterofminds profile image
Justin Hunter

Normally, new things in JS tend to underwhelm me. But this is so freaking awesome! Thanks for writing this up.

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Indeed it is awesome and something that was needed 😀

Collapse
 
anwaar931 profile image
Anwaar Malik

Super awesome and useful feature. Very handy for swift users as well.

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Thank you :)

Glad that you liked it!

Collapse
 
edzward profile image
Edzward

The person example has two firstName. Both "Michael" and "Lampe" have the same firstName variable.

Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Oh noooo!

Thank you!

Changed it 🥳

Collapse
 
guajaro profile image
Julian David Toro

Thanks for sharing

Collapse
 
ryanpwalker profile image
Ryan Walker

Anyone know what the output looks like after running babel?