# Allow Optional Chaining w/ Destructuring

**URL:** <https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960>\
**Category:** 💡 Ideas\
**Created:** [September 2, 2021, 12:27pm UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960 "2021-09-02T12:27:08Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![ethanlal04](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ethanlal04/32/918_2.png) [@ethanlal04](https://es.discourse.group/u/ethanlal04)\
**Post date:** [September 2, 2021, 12:27pm UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/1 "2021-09-02T12:27:08Z")

</div>

I was wondering why optional chaining cannot be used w/ destructuring.

Instead of this...

```javascript
const x = foo.point?.x;
const y = foo.point?.y;
const z = foo.point?.z;

```

Why not...

```javascript
const { ?.x, ?.y, ?.z } = point;

```

Note: I used `point` for simplicity, but the variable on the right could be nested or destructured and thus could be `undefined`.

## Possible Extensions

```javascript
const ?.{ x, y, z } = point; // When all props of an object are optional

```

```javascript
const { coordinates: { ?.x, ?.y, ?.z } } = point; // Nested

```

```javascript
const { coordinates: ?.{ x, y, z } } = point; // Nested All

```

Want only certain props of an object to be required? Hmm... perhaps we can reuse my [required argument syntax](https://es.discourse.group/t/required-arguments/955).

```javascript
const ?.{ x, y, z, direction! } = point; // Same for Nested

```

Thanks, any thoughts?

---

<div class="post-metadata">

**Author:** ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)\
**Post date:** [September 2, 2021, 12:43pm UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/2 "2021-09-02T12:43:34Z")

</div>

> [@ethanlal04](#):
>
> `const { coordinates: { ?.x, ?.y, ?.z } } = point; // Nested`

> [@ethanlal04](#):
>
> `const { coordinates: ?.{ x, y, z } } = point; // Nested All`

I'm not a fan of too much nested destructuring. It obfuscates the variable names you're declaring.

```javascript
const { x, y, z } = point.coordinates ?? {};

```

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [September 2, 2021, 2:55pm UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/3 "2021-09-02T14:55:52Z")

</div>

This desired behavior is possible today, even with the nested syntax form (unless you're also wanting to deal with null properties):

```javascript
const point = undefined
const { coordinates: { x, y, z } = {} } = point ?? {};

```

---

<div class="post-metadata">

**Author:** ![rdking](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rdking/32/54_2.png) [@rdking](https://es.discourse.group/u/rdking)\
**Post date:** [September 2, 2021, 10:19pm UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/4 "2021-09-02T22:19:17Z")

</div>

If I guessed, I'd say the reason is because the meaning causes problems.

First, the optional chaining equivalent of

```javascript
const x = foo.point?.x;
const y = foo.point?.y;
const z = foo.point?.z;

```

would more than likely look like

```javascript
const { x, y, z } = foo.point?;

```

Neither this syntax, nor the one offered before

```javascript
const { ?.x, ?.y, ?.z } = foo.point;

```

can work imo. The one I offered is not the optional chaining operator. Even if it were treated as such, the meaning would be

```javascript
const { x, y, z } = foo.point || null; //Might be undefined. Don't recall.

```

which doesn't work, while the other would be problematic because the first term is a binary operator. That would break destructuring which looks for a valid identifier name as the first term after the braces.

That's not to say it can't be made to work, but it does toy around with the mental model a bit much.

---

<div class="post-metadata">

**Author:** ![ethanlal04](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ethanlal04/32/918_2.png) [@ethanlal04](https://es.discourse.group/u/ethanlal04)\
**Post date:** [September 3, 2021, 5:19am UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/5 "2021-09-03T05:19:40Z")

</div>

> [@rdking](#):
>
> `const { x, y, z } = foo.point?;`

According to what I know, compilers think that this is a ternary expression and complain. That's why optional method calling looks like `foo.bar?.()` and not `foo.bar?()`.

---

<div class="post-metadata">

**Author:** ![rdking](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rdking/32/54_2.png) [@rdking](https://es.discourse.group/u/rdking)\
**Post date:** [September 3, 2021, 12:46pm UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/6 "2021-09-03T12:46:41Z")

</div>

The reason I wrote it that way is because of the semantic meaning of the notations involved. That's where the problems arise.

This is optional chaining.  
\< object being checked for existence \> '?.' \< property being accessed \>

This is destructuring.  
\< declarator \> '{' || '[' \< property being accessed \> \<[':' \< identifier \>]\> \<[',' ...]\> '}' || ']' '=' \< object \>

The thing to the left of the destructuring operator ('?.') must be an object for the same reasons as the '.' operator. Since the '.' is removed when using destructuring, it made sense to me that the same should happen if optionally destructuring.

However, this shows the problem fairly clearly. With normal optional chaining, the engine is either returning the desired property or an "empty" value. Distributing optional chaining over destructuring would mean this:

```javascript
const { x, y, z } = null

```

is the same as :

```javascript
const x = null;
const y = null;
const z = null;

```

which is distinctly not true and would require a modification of how destructuring works.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [September 3, 2021, 1:39pm UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/7 "2021-09-03T13:39:37Z")

</div>

Perhaps another angle to think of the issue, what does this do?

```javascript
const point = undefined
const { ?.x, y } = point

```

It'll throw, because a property y does not exist on undefined. There's no value in applying this "?." syntax to only some of those properties, it's an all or nothing deal. Perhaps that's why @rdking is saying it might be more logical to put the syntax in a location where it can be an all or nothing deal.

```javascript
const point = undefined
const { x, y } = point?.

```

Then, in his version, he was merely omitting the "." from "?.", because the property access is already implied when destructuring. It's not like `const { x, y } = point.` is valid syntax. He was then mentioning some issues with trying to figure out what `point?` would even evaluate to make this all work`. Perhaps a better syntax to achieve this effect would be something like this:

```javascript
const ?{ x, y: ?{ a, b } } = point

```

i.e. I'm prefixing the whole destructuring object syntax with a "?" if I'm ok with it being optional.

Though once again, this syntax is mostly useless unless you're dealing with nested destructuring that has null values, and you don't wish to break up the nested destructuring. I don't know if you have use cases that fall into this category or not, but I'm certainly ok with breaking up a destructuring over multiple lines if I'm expecting a null value.

---

<div class="post-metadata">

**Author:** ![rdking](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rdking/32/54_2.png) [@rdking](https://es.discourse.group/u/rdking)\
**Post date:** [September 3, 2021, 1:59pm UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/8 "2021-09-03T13:59:22Z")

</div>

That's a good portion of it. Since I learned assembly as my second programming language, and C++ as my third, I've always understood operators to be implicit functions. So

```javascript
const { x, y } = point?

```

looks to me like

```javascript
function dereference(object, param) {
   let retval = object;
   if (object && typeof(object) == "object")
      retval = object[param];
   return retval;
}
const x = dereference(point, "x");
const y = dereference(point, "y");

```

However, parallel to what you said, I can't make a sensible function out of putting the operator on the property. So in my head, that notation is an instant fail.

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [September 5, 2021, 11:29pm UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/9 "2021-09-05T23:29:03Z")

</div>

I could see that syntax being extremely convenient with optional options parameters, replacing the `{foo, bar} = {}` idiom with something that no longer requires an object prototype lookup when missing (making it much faster).

---

<div class="post-metadata">

**Author:** ![yjm](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/yjm/32/753_2.png) [@yjm](https://es.discourse.group/u/yjm)\
**Post date:** [September 26, 2021, 2:25am UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/10 "2021-09-26T02:25:01Z")

</div>

How about below:

```javascript
const { a?: { b?: { c } } } = obj

```

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [September 26, 2021, 5:19am UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/11 "2021-09-26T05:19:47Z")

</div>

That would work ok, but we would also need a syntax that works with array destructuring, and there really isn't a way to translate that to arrays.

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [September 26, 2021, 8:26am UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/12 "2021-09-26T08:26:13Z")

</div>

I do see that as an acceptable compromise, though - I don't see myself doing optional destructuring of inner arrays that often, and it's pretty easy to just write another line to continue the destructuring.

---

<div class="post-metadata">

**Author:** ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)\
**Post date:** [September 26, 2021, 9:49am UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/13 "2021-09-26T09:49:30Z")

</div>

> [@yjm](#):
>
> How about below:
> 
> `const { a?: { b?: { c } } } = obj`

That doesn't solve the OP, you'd need to put `obj ?? {}` on the right-hand-side.  
Plus it's 1. drowning the name of the variable "c" in ascii soup; and 2. moving the key "a" further away from the `obj` you're pulling it from.

This is so much clearer:

```js
const c = obj.a?.b?.c;
// or
const { c } = obj.a?.b ?? {};

```

Even though there's still a lot of soup to swim through, at least it reads left-to-right.  
If someone can come up with a clean way to get rid of the `?? {}`, that'd be great.

I get that when you want to pull things from multiple sub-objects, this one line can't do that. But if you have several nested optional objects you want to pull things from, perhaps you should split that into multiple steps — destructure one optional object at a time — for the sake of readability.

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [September 26, 2021, 8:38pm UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/14 "2021-09-26T20:38:40Z")

</div>

Now that I'm thinking about it a bit better, something that works with arguments would be far more useful (and would make the majority of use cases IMHO - think: object-based named parameters), and of course arrays would be naturally included in that.

What about this as assignment patterns as an alternative?

- `?{a} = b` → `if (b != null) {a} = b; else a = undefined`
- `?[a] = b` → `if (b != null) [a] = b; else a = undefined`

---

<div class="post-metadata">

**Author:** ![jb123](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jb123/32/1833_2.png) [@jb123](https://es.discourse.group/u/jb123)\
**Post date:** [August 14, 2023, 8:10pm UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/15 "2023-08-14T20:10:19Z")

</div>

What about a new operator, like `?=`, specifically for optional destructuring:

```javascript
const obj = undefined
const { name } ?= obj

```

OP's destructuring would look like

```javascript
const { x, y, z } ?= foo.point;

```

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [August 14, 2023, 9:03pm UTC](https://es.discourse.group/t/allow-optional-chaining-w-destructuring/960/16 "2023-08-14T21:03:26Z")

</div>

You’d want to do it per-property, I’d think, for nested destructuring as well.
