Comments (19)
I'm confused why this code would even use Because 0 is a number. However to check if something is a number you need to do some coercion checking to make sure. If it's coerced form is equal to it's numerical form then it is a number. Really what we want are more test cases that would be considered valid or invalid:!isNaN(x)
since NaN == false
. That parsing isn't needed.
Tests
validateNumber('10') // true
validateNumber(false) // false
validateNumber(true) // false
validateNumber(10) // true
validateNumber(0.10) // true
validateNumber(010) // true
validateNumber(0xA) // true
validateNumber(NaN) // false
validateNumber(null) // false
validateNumber(undefined) // false
validateNumber('10%') // false, % is a construct
validateNumber('10px') // false
validateNumber(Infinity) // false
validateNumber(Math.PI) // true, but is such an extreme edge case...
validateNumber(0) // true, will probably wreck things
validatenumber(1e10) // true
test based coding is really the only way to infallible say "This method is complete to the best of my knowledge". As new tests fail that should be valid we then know the code is invalid. Fix, iterate, evolve.
Possible Code
const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
Tested Possible Code
Notice negating on false cases. I should expect an entire array of true
EDIT:
Test cases now include an exponential notation number ~ skatcat
from 30-seconds-of-code.
validateNumber('20px') // true
from 30-seconds-of-code.
@Chalarangelo I definitely agree, parsing numbers in javascript is a pain with so many corner cases I lost count (which is why I restrict to usually restrict to strings/numbers and use Number
to parse instead of parseFloat).
By the way the reason the solution works for most cases is that you're using two different kind of number conversions that happen to exclude the wrong results of each other. If it helps I made a document comparing the possible parsing methods to try and figure out the mess: https://gist.github.com/Ephys/4d9731d5c7a945dcc752d279eaeaa08f
from 30-seconds-of-code.
@fesebuv I believe the function is meant to allow a number string as well.
Also OP, what about booleans?
const validateNumber = n => isFinite(n)
validateNumber(true) // true
If it's meant to be an actual number, then Number.isFinite()
should suffice. However, I thought the purpose was to also allow a string as input which makes it more useful when grabbing, for example, text from an input/textarea or an element attribute.
from 30-seconds-of-code.
@atomiks @fesebuv @Chalarangelo
I think this would do:
const validateNumber = n => isFinite(parseFloat(n))
from 30-seconds-of-code.
I think I based the snippet on this SO answer. It might be outdated or there might be something I don't understand. Does anyone know of any cases where Number.isFinite()
alone would fail?
from 30-seconds-of-code.
🤔 what about?
const validateNumber = n => typeof n === 'number';
from 30-seconds-of-code.
Yes, the function is meant to allow strings containing numerical data, such as '10'
for example, to evaluate to true
. @elderhsouza I think this should probably work as intended. Can anyone find any test cases that break this? Otherwise, we should get a PR going and change the current solution to this.
from 30-seconds-of-code.
@atomiks technically speaking '20px'
is a numeric value in CSS. 😛
from 30-seconds-of-code.
I'm using this to test the cases, and to be fair I now think @Chalarangelo was right all along, the first option doesn't break with any test cases so far:
isNumber = n => !isNaN(parseFloat(n)) && isFinite(n)
test = [Infinity, NaN, -Infinity, 0, 2e64, 910, null, '0', undefined, true, '20px', 50, '0xFFFFFF', 0xFFFFFF, '0xfff']
results = test.map(isNumber)
console.table([test, results])
from 30-seconds-of-code.
I told you guys where I think I found the original, but the clarification why it works is unclear on SO. Can anyone figure it out and explain it better so we can update the snippet's description?
from 30-seconds-of-code.
isNumber([1])
returns true. Any object that can be coerced into a number will return true too
I think the only safe way to do it is to explicitly whitelist numbers & strings
isNumber = n => {
const type = typeof n;
if (type !== 'string' && type !== 'number') {
return false;
}
return isFinite(n);
}
Edit 1: Beware of toPrimitive
and toString
too:
obj = {
[Symbol.toPrimitive](hint) {
if (hint === 'string') {
return '10';
}
if (hint === 'number') {
return 10;
}
return true;
}
};
isNumber(obj); // true
obj = {
toString() {
return '10';
}
};
isNumber(obj); // true
Edit 2: Forgot valueOf
but it only is called when converting using Number
, not parseFloat
from 30-seconds-of-code.
@ephys isNumber([1,2])
returns false
, though. I mean an array with just one number sounds reasonably valid to me, as parseFloat([1])
will work properly. JS is weird when it comes to stuff like this.
from 30-seconds-of-code.
@Chalarangelo That's due to coercion (the array is stringified into '1'
then parsed as an int -- notice how parseFloat([1,2])
works too for the same reason) and that has caused more bugs than I can ever count. But if you want to consider arrays and above to be numbers it's up to you and likely depends on what you're trying to achieve :)
from 30-seconds-of-code.
@ephys you make a pretty good point. This can cause trouble, but limiting to specific data types can be troublesome as well. Generally the parsing system of JS is terrible, I mean parseFloat('123I am a little lamb')
returns 123
for no apparent reason. I know why it works and I know this is the defined behavior, but I hate it and there are so many edge-cases that this whole thing becomes a nightmare to deal with.
In general, I agree, numbers and strings that can be converted to numbers should be considered valid by the implemented function (unless the are equal to Infinity
), except that some strings that evaluate to numbers are not really numbers and we need to deal with those, I suppose.
from 30-seconds-of-code.
@atomiks @elderhsouza
in that case:
const validateNumber = n => parseInt(n, 10) => typeof n === 'number';
from 30-seconds-of-code.
@ephys that's a lot of effort you put in, but unfortunately I am too tired to read through the whole thing right now. First thing in the morning, though. I really want to figure out what to do with this specific snippet as I expect it to be used by a lot of people.
@fesebuv this still returns true
for '20px'
, so it's not right yet.
from 30-seconds-of-code.
Resolved in #101 as suggested. If any problems arise, comment below to reopen the issue.
from 30-seconds-of-code.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for any follow-up tasks.
from 30-seconds-of-code.
Related Issues (20)
- Merge two arrays and remove duplicate elements HOT 2
- CSVToArray will return an empty item for documents ending with \n HOT 2
- addDaysToDate fails with non-UTC timezone HOT 1
- A snippet folder dedicated to Angular
- Js
- Broken links HOT 4
- New snippet ideas HOT 1
- passive-scroll-listener-performance has obsolete/incorrect advice HOT 2
- Regarding the throttle function's question. HOT 7
- style: Centering the footer section ⏡ HOT 2
- Website Navigation Bar
- cookie parsing containing a `=` in value HOT 5
- [ BUG ] Missing space in footer section HOT 12
- Typo in the event-loop-explained.md snippet HOT 2
- fix: Unnecessary parameter in Queue class methods HOT 2
- Terminology issue in blog HOT 4
- :bug: Fix Footer settingsPath (GithHub,CC ,30-sec-of-code Link)
- Kindly add hacktoberfest label to your repo. HOT 1
- [Feature Request] : The border of search bar is not clearly visible .
- Typo on the website
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from 30-seconds-of-code.