1

Here is the function, password is mandatory but other id and name have default values:

function name({id = null, name = 'user', password}) { }

Results:

name();     //throws error as expected
name({});   //passes 'password' as 'undefined' - should've thrown error

How can I make this function throw an error if password is not provided using ES6 functionality?

Shaharyar
  • 12,254
  • 4
  • 46
  • 66
  • Why don't you just validate incoming parameters in the function itself and throw if anything is invalid? Heck an empty string or even a non-string could be passed for a password and that would pass any automatic ES6 stuff so you're going to have to validate the password field anyway. Even if you had a hard typed language, you're still going to want to validate. – jfriend00 Jan 08 '17 at 19:05
  • @jfriend00 I agree, but I just want to save code for scenarios where I only have to care about `undefined`. It is just `mcve`. – Shaharyar Jan 08 '17 at 19:10

4 Answers4

4

You could assign the same variable, it throws an error Use before declaration, if not given.

function name({ id = null, name = 'user', password = password }) {
    console.log(password);
}
name({});

If set, then it works without error.

function name({ id = null, name = 'user', password = password }) {
    console.log(password);
}
name({ password: 'foo' });
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • This article is also worth checking out: http://www.2ality.com/2014/04/required-parameters-es6.html – Bartosz Gościński Jan 08 '17 at 18:28
  • why is `,password = password}` different than `,password}` ? – dandavis Jan 08 '17 at 18:32
  • because its a default assignment, with a variable which does not exist. and if it exist, then no assignment occurs. – Nina Scholz Jan 08 '17 at 18:33
  • default assignment is also `undefined`, how is that `undefined` is not equal to `an undefined variable`? I hope I am clear, this `undefined` hell is confusing me. – Shaharyar Jan 08 '17 at 18:48
  • the variable `password` does not exists., even if RHS changed to `_`, it does not exists. it is not defined, and therefore it throws an error. – Nina Scholz Jan 08 '17 at 18:52
  • I know, but if I leave it as `,password` the default assignment is performed and that default assignment is also `undefined` *(I'm using vscode debugger to see this, in nodejs env)* and no there is no error in default. Error is only thrown when I `password = password` and this creates hell lot of confusion for me. – Shaharyar Jan 08 '17 at 19:12
2

You didn't make it required, you simply didn't provide a default value.

function name({id = null, name = 'user', password}) {
     if (password == undefined) {
        throw new Error('password is required');
    }

The reason it threw an error the first time is because it tried to destructure undefined, which is impossible.

Scimonster
  • 32,893
  • 9
  • 77
  • 89
  • I know it can be achieved using ES5 or traditional javascript code, but is there anyway I don't have to write this extra validation and use `ES6 functionality` just like `usecase 1`? – Shaharyar Jan 08 '17 at 18:21
  • No, the "validation" is simply a side effect of destructuring. – Scimonster Jan 08 '17 at 18:22
2

Scimonster's answer is spot-on about what the probelm is.

If you like, you can handle it a bit more declaratively by using a utility function to throw an Error in the function parameter list:

// Utility function:
function throwRequired(name) {
  throw new Error(`'${name}' is required`);
}

function name({id = null, name = 'user', password = throwRequired("password")}) {
  console.log("All is good, password is: " + password);
}

try {
  name();     //throws error as expected
} catch (e) {
  console.log("Got error from name():", e.message);
}
try {
  name({});     //throws error as expected
} catch (e) {
  console.log("Got error from name({}):", e.message);
}
name({password: "foo"}); // works

That works because the initializer on a default parameter is only evaluated if it's required to fill in the default.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
2

Note: This is an ugly hack using the default parameters, and I prefer @Scimonster's answer.

You can actually run a function, and even an IIFE as a default param. The IIFE can throw an error:

function name({
  id = null, 
  name = 'user',
  password = (() => { throw new Error('password not defined'); })()
}) { 
  console.log(id, name, password);
}
  
name({ id: 1, name: 'the name', password: 'the password' }); // works

name({}); // throws an error
Community
  • 1
  • 1
Ori Drori
  • 183,571
  • 29
  • 224
  • 209