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'. Let's discuss what problems it solves, how it works, and how it will make your life easier.
The problem
Imagine the following:
You are working on that piece of code that loads data from an API. The object you are getting back is deeply nested, which means you need to go down a long path of object properties.
// API response object
const person = {
details: {
name: {
firstName: "Michael",
lastName: "Lampe",
}
},
jobs: [
"Senior Full Stack Web Developer",
"Freelancer"
]
}
// Getting the firstName
const personFirstName = person.details.name.firstName;
Not this would be bad practice to leave the code like this right now. A better solution could like this:
// Checking if firstName exists
if( person &&
person.details &&
person.details.name ) {
const personFirstName = person.details.name.firstName || 'stranger';
}
As you see in the example even something simple like getting the firstName of a person can be hard to get right.
So this is why we had frameworks like lodash
to deal with things like this.
_.get(person, 'details.name.firstName', 'stranger');
'loadash' makes the code more readable, but now you have introduced a big dependency into your codebase. You need to update it, and if you ware working on a team, you have to spread the knowledge and use of it to the team. So this is also not the ideal solution.
The Solution
Optional chaining has a solution for all of that (besides the team knowledge problem).
How does it work
Optional chaining introduces new syntax that at first will look strange to you, but after just a few minutes you will get used to it.
const personFirstName = person?.details?.name?.firstName;
Okay, so you probably now have a lot of question marks above your head (pun intended). So the new thing here is the ?
. Here is how you have to think about it. If there is a ?.
at the beginning of a property, it is as you would ask your self does person exists? Or in a more javascript way, has person
the value null
or undefined
? If yes then I will not return an error but just undefined
. So personFirstName
will have the value of undefined
. This question will repeat for details?
and name?
. If any of these values is 'null' or undefined
, then personFirstName
will also be undefined
. This is called Short-circuiting
. Once javascript finds a null
or undefined
it will short circuit and stop going deeper.
Default values
We also need to learn about the Nullish coalescing operator
. Okay, this sounds hard to learn. But actually, it is not. Let's look at the following example:
const personFirstName = person?.details?.name?.firstName ?? 'stranger';
The Nullish coalescing operator
is represented as ??
. It is also pretty easy to read. If the left side is undefined
than personFirstName
will get the value of the right side from ??
. That's it pretty easy.
Dynamic properties
Sometimes you want to access a dynamic value. It could be an array value or just a dynamic property of an object.
const jobNumber = 1;
const secondJob = person?.jobs?.[jobNumber] ?? 'none';
The important thing here to understand is that jobs?.[jobNumber]
is the same as jobs[jobNumber]
but it will not throw an error; instead, it will return 'none'.
Function or method call
Sometimes you will work on objects where you don't know if they have a method or not. Here we can use the ?.()
syntax or with arguments ?.({ some: 'args'})
. It works as you would think it works. If this method does not exist on that object, it will return undefined
.
const currentJob = person?.jobs.getCurrentJob?.() ?? 'none';
If there is no getCurrentJob
function than currentJob
will be none
.
Start using it today
Right now no browser supports this out of the box — Babel to the rescue. There is a babel.js
plugin already that is pretty easy to integrate if you have already Babel setup.
babel-plugin-proposal-optional-chaining
Finale words
I think this will make a lot of Javascript code easier to read and also less error-prone. If you want, you can also read the proposal. I hope that this post made you a little bit smarter, and you now want to integrate Optional Chaining into your workflow!
It would help me if you could do the following for me.
Go to Twitch and leave a follow for me! If just a few people would do that, then this would mean the world to me! ❤❤❤😊
👋Say Hallo! Instagram | Twitter | LinkedIn | Medium | Twitch | YouTube
Top comments (98)
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:
:)
Thanks for the pointer to the babel plugin!
Is there any issue in Ruby with people overusing this feature and it becoming unclear what is nullable and what isn't?
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.
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.
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.
Like always thinking is the key here 😉
IMO it lends itself to patterns like:
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 haveand 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 predictablethis
)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 :)
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.
They plan to add it in TS 3.7.0! 😁
Nice I really need to try TS at some point :)
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? 🤔
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.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 🤣
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.
Are you maybe referring to Ternary operators?
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.
Why
Rather than
?
Good question!
Example time!
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 isfalsy
. The??
just checks fornull
orundefined
.Could also consider converting to a true/false value with:
@joshua I was literally going to say the same thing.
I fail to see the point/usefulness of the '??' operator
There are always alternatives if you can also write
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.Probably that ?? only cares about undefined properties, not null or zero or empty string etc.
It's called nullish for a reason. Because for some reason, JS thought two nulls would be a good idea.
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".
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..
And everybody is true here :)
I try to use
undefined
as much as I can instead ofnull
.But some frameworks want you to use
null
.No use until it is supported by major browsers
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.
Oh didn't see the plugin
there is a link in the
Start using it today
section.babel-plugin-proposal-optional-cha...
yeah got it thanks!
No problem :)
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...
I have a confession to make.
I really really dislike
lodash
andunderscore
.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!
Totally agree:)
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
Try Optional Chaining and Nullish Coalescing on JSitor, its live
Ashvin Kumar Suthar ・ Sep 21 ・ 2 min read
Nice!
I will try it out!
Thanks for the info :)
Thanks.
Your welcome 😀🙌
Yay finally JavaScript is getting inspiration from Kotlin!
Edit: After seeing a few comments looks like this is already in a few other languages
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 🥳
You can always create a C#/Node project and call it from JS :D
Yeah, some other languages also have this!
and finally JS also will have it :)
Sorry for the late reply. Also
Nullish coalescing operator
? Who makes these names? We should call it the elvis operatorUsually, they come from Math people 🤣🤣🤣
No doubt
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.
Okay, why is this crappy?
What do you mean with better code design?
Please explain a little bit more what you mean.
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.
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?
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.
Sorry, I don't fully understand what you mean.
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.
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.
I used this ugly piece:
(((foo || {}).bar || {}).baz || {}).xyz
🥺wow! this is gold
This is a piece of art! 🤣
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.
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 😃👍
One more feature directly copied from CoffeeScript 😅 Great language,shame so few use it anymore.
'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!
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!
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 ;)
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 😅
Haha, that's amazing!
I mean if it works for you why not 😀
Remember using this in CoffeeScript in 2014 lol