2

I need to destruct an object that some of the variables may already have a value.

let foo = 1, bar, baz = 'Hello';

const config = { foo: 42 };

({ foo, bar, baz } = config);

console.log({ foo, bar, baz });

This gives me

{
  "foo": 42,
  "bar": undefined,
  "baz": undefined
}

But what I really want is

{
  "foo": 42,
  "bar": undefined,
  "baz": "Hello"
}

I want to rewrite the value if there is a value with a same name in config, if there's not, use its original value instead.

I can't assign default value while destructuring since the values are assigned previously.

({ foo = 1, bar, baz = 'Hello' } = config);

I know I can assign it like this but it's too clunky since there are more than 20 variables.

({ foo = foo, bar = bar, baz = baz } = config);

Is there a better way to write it without repeating x = x all the time?

Hao Wu
  • 17,573
  • 6
  • 28
  • 60
  • The fact that you have so many standalone variables is a smell. Since it sounds like they're all pretty related - they may be present in `config` - if I were you, consider if you could keep them consolidated in just a single object, it'll let you keep the code a lot more DRY (at least in this section). Once the final object is constructed, *then* destructure later if you need to, IMO – CertainPerformance Feb 04 '21 at 02:12
  • @CertainPerformance I was trying to do that but it's hard to refactor without breaking anything since the values are used everywhere so I gave up eventually. But I absolutely agree with you, it's quite conter-productive this way. – Hao Wu Feb 04 '21 at 02:18

3 Answers3

4

Create an object with the original values (the defaults), and spread the config into it, overriding the default values, and then destructure it:

let foo = 1, bar, baz = 'Hello';

const config = { foo: 42 };

({ foo, bar, baz } = { foo, bar, baz, ...config });

console.log({ foo, bar, baz });
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
1

Object.assign would be a great candidate to resolve your problem. Good luck ^^!

let foo = 1, bar, baz = 'Hello';

const config = { foo: 42 };
const target = {foo, bar, baz};
const source = ({ foo, host, bar } = config);

const result = Object.assign(target, source);
console.log(result);

In case you want to re-assign the variables instead of returning a new object, you can do like below.

let foo = 1, bar, baz = 'Hello';
const config = { foo: 42 };

// Step 1: merge 2 objects
const mergedObject = { foo, bar, baz, ...config };

// Step 2: re-assign variables from `mergedObject`
({foo, bar, baz} = mergedObject);

console.log({foo, bar, baz});
Nguyễn Văn Phong
  • 13,506
  • 17
  • 39
  • 56
0

You can loop config then assign value like this.

let foo = 1, bar, baz = 'Hello';
const config = { foo: 42 };
const result = {foo, bar, baz};

Object.entries(config).forEach(([key, value]) => {
  if(result[key])
    result[key] = value;
});

console.log(result);
Nguyễn Văn Phong
  • 13,506
  • 17
  • 39
  • 56