joi icon indicating copy to clipboard operation
joi copied to clipboard

`required()` vs `valid(...)` - improved separation of concerns

Open DamianGlowala opened this issue 4 years ago • 2 comments

Removed the required context in the issue template as it is unrelevant to my rather generic question.

How can I require a key with Joi and yet accept the following 4 values ("am", "pm", undefined or null) as the only valid ones? It seems odd to me that Joi required() isn't checking only for the existence of the key. In my specific use case, the user can either choose "am", "pm" or undefined (which means no preference). null is here to mark the initial state with no value selected.

If the answer to the above question is that there is no way to achieve this, I would rather say Joi took on a convention which imposes some limitations. By clearly separating the concerns of required() and valid(...)/allow(...), we can neatly achieve the following:

  1. requiring the key itself to be present (we do not care about the value!) - required()
  2. requiring certain values of the key - valid("am", "pm", undefined, null)

DamianGlowala avatar Feb 19 '22 13:02 DamianGlowala

you can use any.empty:

Joi.string().valid('am', 'pm').empty(null) // treat null the same as undefined

Note that you do not want .required() as this key is not mandatory. (if a key is undefined, it's considered as "empty" or "not presence" in your word)

Hint: a key that's undefined will not throw error on referenced, so a falsy check will determine if a key has value.

Assuming myKey is undefined or null, the following if statement will pass: e.g. if(!myKey) console.log('this key does not exist!')

Kanosakl avatar Feb 19 '22 15:02 Kanosakl

Joi was primarily designed with JSON in mind as source, having an object with an undefined key is simply impossible in this case. Does it actually make a difference for you?

Marsup avatar Feb 21 '22 14:02 Marsup