DEV Community

Optional Chaining JavaScript / TypeScript

Nabin Adhikari on July 11, 2018

While working with JavaScript or Typescript, one of my most dreadful experience is reading property of object since there is no optional chaining...
Collapse
 
pichardoj profile image
J. Pichardo

Nice post @nabinadhikari , I actually made a post about this a while ago here, it might be of use.

Collapse
 
nabinadhikari profile image
Nabin Adhikari

@pichardoj Ahh, you have a nice approach for this solution. Thank you for pointing to your post, I've learned lot more from your post about optional chaining.

I see a small issue though, what happen if there is "." in property name like {"H.Angel": {"name": "Angel", "location": "Hobart" }}.

This is a normal case in the project I'm currently working on, so I had to take the different approach.

But again, better approach. I couldn't think of it. :)

Collapse
 
pichardoj profile image
J. Pichardo • Edited

Yeah, that's why I ended using proxies and functions, in order to do something like

optional(obj, obj => obj["H.Angel"].name.location, "Default");
Collapse
 
pmcgowan profile image
p-mcgowan • Edited

There was a massive issue discussion on the TS repo about the "elvis" operator, or safe null coalescing in js. I don't have the link, but a js implementation went to stage 2 IIRC for this exact thing.

Js needs this, as

x && x.y && x.y.z
or
((x || {}).y || {}).z
are obviously terrible.

You could write a simple function using try catch to do this, or prototype on object as well:

Object.prototype._elvis = function (v) {
      let tmp = this;
      try {
          v.split('.').forEach(i => tmp = tmp[i]);
      } catch (e) {
          return null;
      }
      return tmp;
  }

then

x = { y: { z: 2 } };
x._elvis('y.z');  // => 2
x._elvis('y.z.q.r.t');  // => null

Also note - works for null but not undefined.