UPDATE December 2019: This feature has now advanced to Stage-4 and will be part of the ES2020 Specification! 🎉
One of my favorite ECMAScript Proposals is the “Optional Chaining Operator”. Another proposal that forms great duo with it is the “Nullish Coalescing Operator” (sometimes also referred to as “Nullary Coalescing Operator”).
Both proposals still are Stage-1, but don’t let that stop us from taking a peek into it right now.
💁♂️ Stage-1?
The Technical Committee which is concerned with the standardization of ECMAScript (i.e. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.
Stage-1 is the Proposal stage. It signals that the committee is showing interest in the proposal and that it is seeking further investigation on how to tackle it. At this stage the proposal is subject to heavy changes. It is only when a proposal reaches Stage 4 that it is ready to become part of the ECMAScript Specification.
~
The problem
As explained in the “Optional Chaining Operator” post we can get properties of an object in a fail safe way using Short-Circuit Logic or by using the proposed Optional Chaining operator (?.
) in the nearby future:
// Today: Extract firstName using Short-Circuit Logic
const firstName = message.body && message.body.user && message.body.user.firstName;
// Near future: Extract firstName using the Optional Chaining Operator
const firstName = message.body?.user?.firstName;
A common technique used is to add a default fallback value using the logical OR operator (||
):
const firstName = message.body?.user?.firstName || 'Stranger';
Whilst this works fine, there is one problem with falsy values: when the left hand side of the OR expression evaluates to falsy (e.g. null
, undefined
, false
, 0
, empty string, …), the right hand side of the expression will be used. For null
and undefined
that’s not a problem, but it is for false
, 0
, empty string, etc.:
const message = {
settings: {
animationDuration: 0,
showSplashScreen: false
},
};
const showSplashScreen = message.settings?.showSplashScreen || true;
// --> true 🚫
The result here is true
(the fallback), even though message.settings.showSplashScreen
was defined to be false
.
~
The solution
The proposed Nullish Coalescing Operator ??
is intended to provide a solution to this problem. It serves as an equality check against nullary values (e.g.
null
or undefined
). Whenever the expression to the left of the ??
operator evaluates to either undefined
or null
, the value defined to the right will be returned.
Combined with the Optional Chaining Operator, our code snipped can be fixed like this:
const message = {
settings: {
animationDuration: 0,
showSplashScreen: false
},
};
const showSplashScreen = message.settings?.showSplashScreen ?? true;
// --> false 🎉
Small change, big impact 🙂
~
So, when can we us this?
You can use the Nullish Coalescing Operator today already thanks to Babel’s plugin-proposal-nullish-coalescing-operator
plugin (for use with Babel 7).
Do note that the proposal still Stage-1 (soon Stage-2 by the looks of it) and might still change in the future.
~
In short
💻 The examples embedded in this post are part of a talk on ESNext named “What’s next for JavaScript?”, which I recently gave at a Fronteers België meetup and Frontend United 2018 (Utrecht). You can check the slides / a recording out here. I’m available for bringing this talk at your meetup/conference.
👋 This post also got published on Medium. If you like it, please give it some love a clap over there.
📚 Other posts in this series include:
Consider donating.
I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!
I guess I’m not understanding why you would default message.settings.showSplashScreen to false while defaulting const showSplashScreen to true if message.settings?.showSplashScreen is false… seems like contradictory defaults.
Think of
message
as being a response from a serverside config. By default the app would show a splashscreen, unless the config overrides it.Or just use
const showSplashScreen = message.settings?.showSplashScreen !== false;
Yes, that’ll also work in this specific use case but might break when the input changes: what if
0
(the number) gets passed in? That’s also falsy (e.g. “don’t show it”), but will yieldtrue
using your snippet.In the example shown the value for
showSplashScreen
is quite controlled, but imagine a user inputting content: they can enter just about anything (numbers, strings, etc.)The advantage of using
??
is that it works with any type of value as long as it’s notnull
/undefined
. Perfect for setting default values when no input was received 🙂