I often do stuff like this:
delay = delay || 24; // default delay of 24 hours
But I actually want to permit 0, and 0 || 24 === 24
, instead of 0
.
I'm wondering what the best pattern is to take user input from command line, or input from wherever, and do the same logic, only treat zero as truthy. I think the best pattern I've found is to do exactly that:
delay = (delay === 0 ? delay : (delay || 24));
Firstly, it permits things like 'abc'
, which is really wrong. But if I put in an early +
it lets null
slide through, which is also wrong. Secondly, very ugly, because it's clearly working around a language deficiency rather than doing something elegant with the language tools available. And not terribly readable. I'm doing something that is one line of thought and I'd like to do it in one actual line of code (not one line on technicality, like this is). But most other ideas I have had get even uglier:
delay = typeof delay === 'number' ? delay : 24; // but typeof NaN === 'number', so
delay = (!isNaN(delay) && typeof delay === 'number') ? delay : 24;
Note that this actually would work with string - if i were interested in accepting ""
, then
str = typeof str === 'string' ? str : 'default';
Since there is no NaN
hole, and this is intelligently readable: if we have a string use that, otherwise use defaut.
Or this route:
delay = !isNaN(+delay) ? delay : 24; // fails on null
delay = !Number.isNaN(+delay) ? delay : 24; // still fails on null
// same thing with null check, now way uglier than we started
So I still like my hacky ternary and boolean logic better. Yes, I am looking for a condensed, one-line solution, since JS is rife with patterns and what would be clever in many other languages is well-recognized and readable and clear in JS. But I'm novice and trying to learn good patterns, hence, this question.
To be more explicit on the requirements:
0
needs to go to0
.undefined
needs to go to24
.- All actual numbers under
typeof
need to go to themselves, exceptNaN
. - I strongly feel
null
should go to24
because I very rarely use JS code that treatsnull
andundefined
differently on purpose. I feel it's better to keep it that way. - I slightly feel
NaN
should go to24
because this more closely follows the||
pattern. Falsy things should go to default. 'abc'
should go to 24 - in my real application this is user input, and the user should not mistakenly type, say an email.'123abc'
should ideally go to24
, which conversion toNumber
catches butparseInt
does not. I believe emails can start with numbers, so this drives the point home that this is something that ought to be caught.
Underscore or lodash answers are acceptable, in particular, to those of you who have lectured me on trying to be "clever" instead of writing a 2-3 line function. Those libraries exist precisely because there are many simple 2-3 line functions accomplishing the same thing in many places in many code bases all over the world, and it's far more readable and maintainable and robust to have those isolated as something like, say, _.readNumber
. If no such method exists and I am able to come up with general enough requirements, I will submit a poll request myself and post that as answer to this question. This is something I like about JS - it has good ecosystem in that it's very possible to not have to write these utility methods. Since I'm particularly dealing with user input it may be better for me to write a slightly more specialized function and submit to commander.js, which is where I keep needing this.