JS/ES6: Destructuring of undefined
JavascriptEcmascript 6Javascript Problem Overview
I'm using some destructuring like this:
const { item } = content
console.log(item)
But how should I handle content === undefined
- which will throw an error?
The 'old' way would look like this:
const item = content && content.item
So, if content
is undefined -> item
will also be undefined.
Can I do something similar using destructuring?
Javascript Solutions
Solution 1 - Javascript
You can use short circuit evaluation to supply a default if content
is a falsy value, usually undefined
or null
in this case.
const content = undefined
const { item } = content || {}
console.log(item) // undefined
A less idiomatic (see this comment) way is to spread the content into an object before destructuring it, because null
and undefineds
values are ignored.
const content = undefined
const { item } = { ...content }
console.log(item) // undefined
If you are destructuring function params you can supply a default (= {}
in the example).
Note: The default value would only be applied if the destructured param is undefined
, which means that destructuring null
values will throw an error.
const getItem = ({ item } = {}) => item
console.log(getItem({ item: "thing" })) // "thing"
console.log(getItem()) // undefined
try {
getItem(null)
} catch(e) {
console.log(e.message) // Error - Cannot destructure property `item` of 'undefined' or 'null'.
}
Or even set a default value for the item
property if the input object doesn't contain the property
const getItem = ({ item = "default" } = {}) => item
console.log(getItem({ item: "thing" })) // "thing"
console.log(getItem({ foo: "bar" })) // "default"
Solution 2 - Javascript
const { item } = Object(content)
Solution 3 - Javascript
Destructuring the nested object is clean and short but sucks when source property is null
or undefined
in right side object
let say we have
const {
loading,
data: { getPosts },
} = useQuery(FETCH_POSTS_QUERY);
Solution 1
if we have data object but no getPosts
then we can use:
(Setting default at each level)
const {
loading,
data: { getPosts = [] } = { getPosts: [] },
} = useQuery(FETCH_POSTS_QUERY);
Solution 2:
if event data
is undefined
then:
const {
loading,
data: { getPosts } = { getPosts: [] },
} = useQuery(FETCH_POSTS_QUERY);
Solution 4 - Javascript
One can unpack undefined value, but can't unpack from undefined.
Fixing it is as easy as setting the default params value.
Example:
(() => {
// prepare payload
const PAYLOAD = {
holdingJustThis: 1
};
// lets unpack the payload and more
const {
holdingJustThis,
itIsGoingToBeUndefined,
itCouldThrowButWont: {
deep
} = {} // this will secure unpacking "deep"
} = PAYLOAD;
console.log({
holdingJustThis
});
console.log({
itIsGoingToBeUndefined // logs {itIsGoingToBeUndefined:undefined}
});
console.log({
deep // logs {deep:undefined}
});
})()
Solution 5 - Javascript
accepted answer does not work for truely undefined values which were not set by const content = undefined
. in such cases this will work:
const { item } = (typeof content !== 'undefined' && content) || {}
console.log(item)
Solution 6 - Javascript
const content = undefined
const { item } = content ?? {}
console.log(item) // undefined
Solution 7 - Javascript
I'll just add that for the OP's use case, it is also possible to use the Optional chaining operator:
const item = content?.item
console.log(item)
If content
is null or undefined, then content.item
will not be accessed and item
will be undefined.