122

I'm trying to figure out if there's a way to use object destructuring of default parameters without worrying about the object being partially defined. Consider the following:

(function test({a, b} = {a: "foo", b: "bar"}) {
  console.log(a + " " + b);
})();

When I call this with {a: "qux"}, for instance, I see qux undefined in the console when what I really want is qux bar. Is there a way to achieve this without manually checking all the object's properties?

Quentin Roy
  • 7,677
  • 2
  • 32
  • 50
user3019273
  • 1,323
  • 2
  • 8
  • 4

1 Answers1

241

Yes. You can use "defaults" in destructuring as well:

(function test({a = "foo", b = "bar"} = {}) {
  console.log(a + " " + b);
})();

This is not restricted to function parameters, but works in every destructuring expression.

Quentin Roy
  • 7,677
  • 2
  • 32
  • 50
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 3
    Nifty! It seems like setting the defaults on the destructuring side (the way you're doing it) would always be preferred to doing it on the default parameter side (like I was). Would you agree with that? Can you think of anything to watch out for? – user3019273 Oct 26 '14 at 21:59
  • 6
    I don't think one is "preferred" over the other. It just does something else. – Bergi Oct 26 '14 at 22:01
  • 1
    This guards against `undefined`, but still errors if `b` is `null` right? Any way to protect against both `undefined` and `null` when destructuring? Ex: `{a: "qux", b: null}` would still error. – Alan Hamlett Oct 04 '17 at 22:15
  • 3
    @AlanHamlett No, destructuring only deals with `undefined` - passing `null` must be done explicitly, and therefore leads to an error. To deal with both `null` and `undefined`, use the standard `b == null ? "bar" : b` inside the function. – Bergi Oct 04 '17 at 23:47
  • 3
    @Bergi Could you explain what the difference between your answer and `test({a="foo", b="bar"})` is? – Yonggoo Noh Feb 02 '18 at 04:59
  • 5
    @YonggooNoh See [here](https://stackoverflow.com/a/41108626/1048572) and [here](https://stackoverflow.com/q/34275971/1048572) – Bergi Feb 02 '18 at 09:12
  • Basically, if you want to do just `new YourClass()`, use `= {}` if some parameters are mandatory, don't. – jave.web Mar 13 '22 at 13:37
  • Typescript doesn't seem to recognize this well : ( – B T Dec 30 '22 at 03:03
  • @BT Yes it does. If you're having trouble to make it work (or add type annotations), please [ask a new question](https://stackoverflow.com/questions/ask) and share the code that doesn't work – Bergi Dec 30 '22 at 03:04
  • @Bergi I've figured out my typescript issue. The type must describe the acceptable *argument*, and not the resulting *parameter* type. IE in this case, the argument can accept undefined values for the defaulted parmaters, while the *parameters* themselves will never have undefined values for the defaulted parameters. Just a bit confusing. – B T Dec 30 '22 at 06:01
  • plus some info, you can rename prop like this: ` (function test({a = "foo", b:c = "bar"} = {}) { console.log(a + " " + c); })();` – JackChouMine Feb 08 '23 at 01:17