I have an object that has lots of deeply nested properties. I want to be able to access properties on "MY_KEY" (below), but if that doesn't exist then get "MY_OTHER_KEY". How can I accomplish that?
const {
X: {
Y: {
MY_KEY: {
Values: segments = []
} = {}
} = {}
} = {}
} = segment;
I have an object that has lots of deeply nested properties. I want to be able to access properties on "MY_KEY" (below), but if that doesn't exist then get "MY_OTHER_KEY". How can I accomplish that?
const {
X: {
Y: {
MY_KEY: {
Values: segments = []
} = {}
} = {}
} = {}
} = segment;
Share
Improve this question
edited Aug 14, 2018 at 4:15
Gibolt
47.1k15 gold badges206 silver badges133 bronze badges
asked Oct 18, 2017 at 17:39
mergesortmergesort
5,19713 gold badges40 silver badges64 bronze badges
7
|
Show 2 more comments
3 Answers
Reset to default 7You could achieve this using a temporal variable inside your destructuring assignment, something like this:
function destructure(segments) {
const {
X: {
Y: {
MY_OTHER_KEY: _fallback_value = {},
MY_KEY: {
Values: segment = []
} = _fallback_value,
} = {},
} = {},
} = segments;
return segment;
}
console.log(destructure({})); // []
console.log(destructure({X:{}})); // []
console.log(destructure({X:{Y:{MY_KEY:{Values:"A"}}}})); // A
console.log(destructure({X:{Y:{MY_OTHER_KEY:{Values:"B"}}}})); // B
console.log(destructure({X:{Y:{MY_OTHER_KEY:{Values:"C"}, MY_KEY:{Values:"D"}}}})); // D
First of all, this kind of destructuring will attempt to extract the second key all the time, which might have some unintended implications, like a property getter for MY_OTHER_KEY
will always run.
However I fail to see the beauty in it. Hiding some control flow inside destructuring is just confusing. I would rather suggest extracting the parent object and use regular property access on it:
function destructure(segments) {
const {
X: {
Y: nested = {},
} = {},
} = segments;
const selected = nested.MY_KEY || nested.MY_OTHER_KEY || {};
const {
Values: segment = []
} = selected;
return segment;
}
console.log(destructure({})); // []
console.log(destructure({X:{}})); // []
console.log(destructure({X:{Y:{MY_KEY:{Values:"A"}}}})); // A
console.log(destructure({X:{Y:{MY_OTHER_KEY:{Values:"B"}}}})); // B
console.log(destructure({X:{Y:{MY_OTHER_KEY:{Values:"C"}, MY_KEY:{Values:"D"}}}})); // D
While object destructuring is cool and new, it is not the best in all cases. May do:
try {
var segments = segment.X.Y.MY_KEY.Values;
} catch(e){
//whatever
}
Check if the target is defined
let {/* do destructuring stuff */}
if (MY_KEY === undefined) {
// define `MY_OTHER_KEY` variable here
}
If you are trying to assign target to a different property if the previous target definition is undefined
you can assign the variable at subsequent target definition
const segment = {Y:123};
let or = "Y";
let X;
({X, X = X || segment[or]} = segment);
console.log(X);
undefined
, but how do you select the alternative? – kabanus Commented Oct 18, 2017 at 17:41MY_KEY
with value ofMY_OTHER_KEY
within target ifMY_KEY
isundefined
within source? – guest271314 Commented Oct 18, 2017 at 17:50