my linter is giving me trouble about destructuring.
When I'm trying to destructure, it makes me an error, like in the following snippet :
const data = {
status: 'example',
};
let status = 'foo';
{
status,
} = data;
console.log(status);
Is there any ways to use destructuration when the variable already exists?
Using let again :
const data = {
status: 'example',
};
let status = 'foo';
let {
status,
} = data;
console.log(status);
Add parenthesis around destructuring
From the documentation: Assignment without declaration
The parentheses ( ... ) around the assignment statement are required when using object literal destructuring assignment without a declaration.
{a, b} = {a: 1, b: 2} is not valid stand-alone syntax, as the {a, b} on the left-hand side is considered a block and not an object literal.
However, ({a, b} = {a: 1, b: 2}) is valid, as is var {a, b} = {a: 1, b: 2}
Your ( ... ) expression needs to be preceded by a semicolon or it may be used to execute a function on the previous line.
const data = {
status: 'example',
};
let status = 'foo';
({ status } = data);
console.log(status);
Related
Suppose I have some key-value object. I want to destructure dynamically from some key such that I can remove it and just get the remaining items in a new object.
const omit = (obj, key) => {
const { [key], ...rest } = obj // Syntax error
return rest
}
omit({ b: 1, c: 2, d: 3 }, 'd')
// desired output { b: 1, c: 2 }
Is there a way to do that?
Disclaimer: I know there are lots of workarounds but would like to do it with destructuring.
In order to destructure on a dynamic key you will need to provide an alias for JS to bind that value to.
Firefox even gives you a helpful error message here:
const omit = (obj, key) => {
const { [key]: _, ...rest } = obj
// CHANGE -----^
return rest
}
console.log(omit({ b: 1, c: 2, d: 3 }, 'd'))
You can rename the variables when destructuring, and the left side (preexisting name) can be in brackets like you want.
let {[key]: omitted, ...rest} = a;
If function parameter is empty is there a way to pass ...rest of the destructured values to that parameter with spread operator?
For an example:
const obj = {
/* param: {
a: 2,
b: 3
}, */
c: 1,
d: 3
}
const fun = ({ param = ...rest}) => {
console.log(param);
};
fun(obj);
In this case param is "undefined" and i would like to get the rest of the obj assign to the param {c:1, d:3}
In case when param is defined, I would like to have param data {a:2, b:3}
Use a ternary operator in the function parameter section to determine which properties to log:
const obj = {
/*param: {
a: 2,
b: 3
},*/
c: 1,
d: 3
}
const fun = (args = obj.param ? obj.param : obj) => {
console.log(args)
}
fun(obj)
Is it possible to use a destructuring assignment inside an object?
This works
const test = {a: 'hey', b: 'hello'}
const {a,b} = test;
const destruct = {
a,
b
};
Would like to do this
const test = {a: 'hey', b: 'hello'}
// something like this
const destruct = {
{a,b}: test
};
const destruct = {
{a}: test,
{b}: test
};
If I understand correctly, it seems the spread syntax is a good fit for what you need.
The spread syntax "..." allows you to "spread" the key/value pairs from a source object (ie test) to a target object (ie destruct):
const test = {
a: 'hey',
b: 'hello',
c: 'goodbye'
}
const destruct = {
// {a,b}: test <-- invalid syntax
...test // equivalent using the "spread" syntax
};
console.log(destruct)
Additionally, if you wanted to select a subset of keys from a source object and spread those into a target object then this can be achieved by the following:
const test = {
a: 'hey',
b: 'hello',
c: 'goodbye'
}
/* Spread subset of keys from source object to target object */
const welcomeOnly = {
...({ a, b } = test, { a, b })
}
console.log('exclude goodbye, show welcomes only:', welcomeOnly);
The second example works by destructing the source object (ie test) into an object, with the subset of keys that we want (a and b).
In the scope of that expression (ie everything between the ( and )), these keys are accessible as local variables. We take advantage of this, and pass those to a new object (ie { a, b }). Because the new object is declared after the ,, it is returned as the result of the expression.
If you are trying to take a subset of properties you can use the rest operator
const test = {
a: 'hey',
b: 'hello',
c: 'goodbye'
};
const { c, ...destruct } = test;
console.log(destruct);
This assigns c to a const and the the left over properties are assigned to the const destruct. List all the unwanted properties first and then the left over properties are caught with the rest operator.
Works with arrays as well.
const test = ['hey', 'hello', 'goodbye'];
const [ first, ...rest ] = test;
console.log(rest);
You can try to work like this for destructuring arrays!
let abc = {
a: 'hello',
b: 'hey',
c: 'hi, there!'
}
let {a: x, b:y, c:z} = abc;
console.log(x,y,z)
// "hello"
"hey"
"hi, there!"
Let's say I have code that requires access to a state object that looks like this
const store = {
getState: () => ({
a: "test",
b: 1,
c: 23,
})
}
And a helper function that looks like this, the rest is to illustrate the fact that the output of this will not be JUST the destructured argument I passed in.
function printState ({a, b, ...rest}) {
console.log(a, b, rest)
}
So if I try to use inline destructuring
printState({ a, b } = store.getState())
The output of above is
"test" 1 Object {
c: 23
}
I would have expected only a and b to be passed in, and not the rest of the object. Does anyone know why this is the case?
{ a, b } = store.getState() is an assignment expression and the value returned by that will always be the expression on the right hand side which is store.getState().
If you want only a and b then you can use and IIFE.
const store = {
getState: () => ({
a: "test",
b: 1,
c: 23,
})
}
function printState ({a, b, ...rest}) {
console.log(a, b, rest)
}
printState((({a,b}) => ({a,b}))(store.getState()))
printState({ a, b } = store.getState())
^^^^^^^^^^^^^^^^^^^^^^^^^^^
since it's an assignment expression which returns the right hand side value, so your this function invocation is actually evaluated something like this
function printState(_ref) {
var a = _ref.a,
b = _ref.b,
rest = _objectWithoutProperties(_ref, ["a", "b"]);
console.log(a, b, rest);
}
printState((_store$getState = store.getState(),
a = _store$getState.a,
b = _store$getState.b,
_store$getState)
);
so you actually end up with printState(store.getState())
You can paste your code here and see Babel
I am looking for the most concise way to have a new object out of the fields of the deconstructed one.
let obj = {
a: 1,
b: 2,
c: null
}
Currently I have:
let {a, c} = obj;
let data = {a, c}
What I wished I would be having:
let data = {a, c} = obj;
// but data actually becomes {a, b, c}
// and not {a, b} as I wished it to be.
Although your code looks fine may be if your task consists in cherrypicking keys and put it in another object destructuring is not the best approach:
const object = { a: 5, b: 6, c: 7 };
const picked = (({ a, c }) => ({ a, c }))(object);
console.log(picked)
You can define a function that will provide the destructured object as the return value, and assign the call to data:
const obj = {
a: 1,
b: 2,
c: null
}
const partial = ({ a, c }) => ({ a, c })
const data = partial(obj)
console.log(data)
Unfortunately this isn't possible in one line without some setup, but the setup is worthwhile if you are creating the same partial object a lot of places in your source.
Rather than rely on destructuring for this, you can implement a version of the commonly found "pick" function, that accepts as input an object and an array of keys to pull out of that object:
function pick(obj, keys) {
return keys.reduce((memo, key) => {
memo[key] = obj[key];
return memo;
}, {});
}
const obj = { a: 1, b: 2, c: 3 }
const data = pick(obj, ['a', 'b']);
console.log(data); // { a: 1, b: 2}
Normally I would consider performance less important than readability, which is highly subjective. But in this case, both the pick solution above and the one-liners are orders of magnitude slower than your original two-liner, though pick wins out over the one-liner by a comparatively small margin: https://jsperf.com/testaagwt14124oih1oij