Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

destructuring #6

Closed
williamkapke opened this issue Jun 22, 2017 · 9 comments
Closed

destructuring #6

williamkapke opened this issue Jun 22, 2017 · 9 comments

Comments

@williamkapke
Copy link

The destructuring scenario doesn't seem like it has been discussed. I don't think there is an intent to create any special magic for it. So, this issue just serves to get more people thinking about it 🤔

Here we go:

const { a, b } = my?.unknown?.chain;

Without any special magic, this will give Cannot match against 'undefined' or 'null'. when the chain does not resolve.

This could be avoided by doing:

const { a, b } = my?.unknown?.chain || {};

Things could get harder (and magic more appreciated) if we start dealing with nesting...

const { a, b:c } = my?.unknown?.chain || { b:{} };

Since "magic" is a terrible word to use, let's replace it with: "additional sugar under certain scenarios" or maybe... "custom functionality that enables an otherwise unachievable outcome."

For example, there COULD be a desire to assign undefined to all values if the chain fails.

The code below, couldn't assign both r and z to undefined without special treatment:

const { x, z:{y:r}, z } = my?.unknown?.chain;

Again, I'm not advocating for anything in particular- just planting some thought seeds. Maybe something to note in the readme?

@ljharb
Copy link
Member

ljharb commented Jun 23, 2017

Since destructuring is sugar for property lookup while creating vars, and this proposal adds sugar for optional property lookup, it sounds like you're looking for sugar for optional property lookup while creating vars. Something like the following, perhaps?

const { x, ?y, ?z: { a: r } } = undefined; // x throws, y and z do not; if z is not destructurable, a throws
/* or */
const ?{ x, y, z: { a: r } } = null; // nothing throws

@claudepache
Copy link
Collaborator

One should start to articulate use cases and issues with the current destructuring semantics, then consider what is the more appropriate syntax for resolving that — instead of trying to find use cases for a given syntax. As @ljharb showed in the previous comment, the best solution may be unrelated to ?.

As currently specced, {a,b} = c?.d will throw if c?.d is undefined, which is fine in case we want to add a more elaborate behaviour “later” (unlikely in my opinion, but anyway...)

@littledan
Copy link
Member

littledan commented Jul 18, 2017

@williamkapke Wouldn't these scenarios be handled by pure destructuring? Not sure if this is intelligible, but it's there... This raises a point about the proposal: Is it a little weird that = {} on the LHS somehow corresponds to ?. on the RHS, but the tokens have nothing to do with each other? (FWIW it seems to me that ?. would be easier to learn and understand.)

const { unknown : { chain: { a, b } = {} } = {}}  = my;

We could also add a defaulting operator, like C#'s ?? to be a better || for the RHS, which has been discussed in es-discuss and TC39. (EDIT: and in #9 in this repository.)

@williamkapke
Copy link
Author

@littledan Good point: It seems like using defaults with destructuring will ...almost work-- it still throws the error if the value resolves to undefined or null, even if all default values are supplied. Maybe just a Chrome thing? Either way that's not ?.'s problem (as others have said).

So, I guess- my current opinion is that this spec doesn't need anything for destructuring! I think this thread alone will help folks know and understand their options for using the features together.

@emattias
Copy link

I am sorry for commenting on this closed issue but this is a big disappointment for me. Me (and my team) generally structure our code by first destructuring out the variables we need and then do logic on them later on in the code. This results in less deep variable fetching "noise" is in the "logic" part of the code.

I was hoping that you would be able to destructure conditionally with this proposal, like @ljharb proposed:

const { ?a: { ?b: { ?c } } } = {}

Is it correct that with this proposal there is still no way to safely destructure a deep object several levels down, without the risk of throwing, if some level is not a destructurable value?

@claudepache
Copy link
Collaborator

@emattias

You can use defaults:

const { a: { b: { c } = {} } = {} } = {}

Anyway, optional destructuring is out of the scope of this proposal. If you think that destructuring has shortcomings that are worth to be addressed, you should discuss them on the es-discuss mailing list.

@mvirbicianskas
Copy link

Wouldn't this result in 'silent' errors? Like if you would use c somewhere in the code and it got undefined you would have to investigate which part of destructured object is undefined, no?

IMO, I don't think it's a good idea to pass on undefined to non-existent object properties as part of destructuring.

Also, I'd agree with @claudepache point.

@jwulf
Copy link

jwulf commented Mar 6, 2018

const { a: { b: { c } = {} } = {} } = {}

Please do not make JavaScript look like this. #LISP

@ljharb
Copy link
Member

ljharb commented Mar 6, 2018

@jwulf that’s all part of JS for 3 years now. Please avoid unproductive comments.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants