A few days ago, an announcement that many expected was published in TC39 Stage 3. Optional Chaining
Example here with
It is a great news for Javascript ! This feature is awesome but...
Please agree with me, this feature will not be available tomorrow in our browsers. In stage 3, it is very likely that this feature will be added in the next release of ES.
But
We will need to babel it for a very long time.
If you take a look at @babel/plugin-proposal-optional-chaining, this is how babel will transpile it.
This is kind of a very verbose output.
Let's imagine that we use this feature very many times in a web application, and you use it for deep case.
const foo = everything?.could?.be.nullable?.maybe
// Babel will generate this output
var _everything, _everything$could, _everything$could$be$;
var foo = (_everything = everything) === null || _everything === void 0 ? void 0 : (_everything$could = _everything.could) === null || _everything$could === void 0 ? void 0 : (_everything$could$be$ = _everything$could.be.nullable) === null || _everything$could$be$ === void 0 ? void 0 : _everything$could$be$.maybe;
// Terser would modify like this
l,n,o;null===(l=everything)||void 0===l||null===(n=l.could)||void 0===n||null===(o=n.be.nullable)||void 0===o||o.maybe
It's going to be really verbose in your bundles. The transformation made by babel in the state does not at all share the nullsafe access mechanism as lodash.get can do. Even if lodash is very/too heavy. It offers a more efficient nullsafe implementation while generating less code.
You're going to tell me,
"What the heck! Antoine, it's not the first time we've used a not-so-great polyfill to be able to use a new feature of EcmaScript"
Yeah
Ok but this time we can still look a few minutes to propose an implementation of a less trivial polyfill. This solution cannot really be applied in a world where the web developer turns into a Ko hunter.
Let's look at how lodash.get works. Github link
import castPath from './castPath.js'
import toKey from './toKey.js'
/**
* The base implementation of `get` without support for default values.
*
* @private
* @param {Object} object The object to query.
* @param {Array|string} path The path of the property to get.
* @returns {*} Returns the resolved value.
*/
function baseGet(object, path) {
path = castPath(path, object)
let index = 0
const length = path.length
while (object != null && index < length) {
object = object[toKey(path[index++])]
}
return (index && index == length) ? object : undefined
}
export default baseGet
It's very effective (very compact). What if the polyfill of the Optional Chaining involved the application of a utility function like lodash.get?
What's your opinion on that?
Feel free to share and react if you liked this article.

Latest comments (34)
Not a problem to me it's designed this way. I'm not seeing the problem?
what do people think of this debugging focused cousin of lodash.get, I call it "safeGet"
I wasn't able to add lookup to the Object.prototype because I was getting this error with my CRA v3+CRACO setup...
"Invariant Violation: EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering,
lookup"The stack trace was pure webpack hell, did not include it in my google search..
I tried adding it directly in my index.html in a script tag but that didn't fix it. I could, however, delay defining it for 5 seconds via setTimeout and I can then define Object.prototype.lookup
I'd really love this api:
someObject.lookup('some.really.long.property.path') - works essentially just like lodash.get or optional chaining. But what if you want to know why the lookup failed?
just print someObject.lastLookupMsg
As a failsafe, is the last lookup was successful.. this could be set to
true(there is no meaningful message for successful lookups)If the last lookup failed, it COULD just automatically console.log("Lookup failed: some.really.long is:", some.really.long, "some.really is:", some.really);
Maybe there could be a cousin to optional chaining ?. – perhaps ~. Means "tread carefully" and returns the last property lookup that was not undefined/null.
Or perhaps ?. could have a debugging version which does the console.log for you in development only.
At the end of the day I think I would prefer to use a simple Object.prototype.lookup method that automatically console.log's the message I described.
One issue is that passing an object lookup path as a string results in no syntax highlighting, you probably lose out on a bunch of other potential ide goodies, but from what I know they mostly don't apply to the main use case of check data from the user or from over the wire.
I'm very much in agreement with you, but for different reasons
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.
I have a proposition, slap it into a babel plugin and just give people option - some (most?) people will choose your version and that will be it :)
Friends don’t let friends use lodash :)
This feature sounds rather pointless to me right now. I wonder what the performance implications of using something like this is.
Ramda pathOr? I guess it doesn't tell you where in a path it breaks with a null. But I like it!
I think it's interesting, but I don't know if it's really good.
On the one hand, most of my errors are related to the problem this proposal tries to solve.
On the other hand, I never checked how often I can get along with
null/undefinedand NOT crash.I mean sure, in some UI code I just want to display a value and if I don't get it, I can display nothing and be done with it.
But when I need an ID to get something from a back-end?
Promises are eating my errors like nobodies business already, now this? I don't know XD
My opinion is along the lines of the general consensus: Optional chaining sure is compact... but VERY ugly if a polyfill is needed, along with an implicit acceptance of the risk of NULL / undefined data, which I am personally opposed to. As syntactic sugar goes, it makes things easier - but the ugliness of polyfills for JS gives me pause on adopting it now.
You can do this today with just a recursive proxy that returns an object if undefined.
I hate this pattern. I hate lodash getter, and I hate optional chaining.
You have to answer the question “why” some key is empty, and what you are going to do then - handle the root cause, not the consequences.
Because it's some response coming from the server without any type safety, maybe.
I like the safe navigation operator, but I fear its usage. One level is ok, two might be acceptable, but beyond that you are doing things wrong.
It is nice for templates. But for normal programming? What are you doing so deep in an object structure?
Exactly the point! If a top level
keyis not accessible, then:null,undefined, so you can't go deeper, or itstring, and your data type is too mutable? It's a quite popular to have something which could be "string/object" or "object/function". Why?I agree, overuse of optional chaining and null-coalescing is something that code styles and guidelines will have to limit.
As I see it, it will mostly be useful for things like options objects loaded from a JSON or YML file, where you have settings that may or may not be set, and often 1-3 levels deep. Or when loading documents from a MongoDB where you have set of properties and data that may or may not be there.
When you're working with data coming in from an external source (user input, rest api, database, ...) you can never be 100% certain that it won't be null.
Data structures inside your application should indeed be designed to always adhere to the same strict schema, although even that isn't always the case.
Also: that's a very strong reaction to have to a piece of programming syntax.
I live in a world where
Everything 👏could 👏be 👏 nullable 👏
I really think that being able to design an application where nothing is
nullis a utopia.