I\'m hoping there\'s something in the same conceptual space as the old VB6 IsNumeric()
function?
function isNumberCandidate(s) {
const str = (''+ s).trim();
if (str.length === 0) return false;
return !isNaN(+str);
}
console.log(isNumberCandidate('1')); // true
console.log(isNumberCandidate('a')); // false
console.log(isNumberCandidate('000')); // true
console.log(isNumberCandidate('1a')); // false
console.log(isNumberCandidate('1e')); // false
console.log(isNumberCandidate('1e-1')); // true
console.log(isNumberCandidate('123.3')); // true
console.log(isNumberCandidate('')); // false
console.log(isNumberCandidate(' ')); // false
console.log(isNumberCandidate(1)); // true
console.log(isNumberCandidate(0)); // true
console.log(isNumberCandidate(NaN)); // false
console.log(isNumberCandidate(undefined)); // false
console.log(isNumberCandidate(null)); // false
console.log(isNumberCandidate(-1)); // true
console.log(isNumberCandidate('-1')); // true
console.log(isNumberCandidate('-1.2')); // true
console.log(isNumberCandidate(0.0000001)); // true
console.log(isNumberCandidate('0.0000001')); // true
console.log(isNumberCandidate(Infinity)); // true
console.log(isNumberCandidate(-Infinity)); // true
console.log(isNumberCandidate('Infinity')); // true
if (isNumberCandidate(s)) {
// use +s as a number
+s ...
}
Save yourself the headache of trying to find a "built-in" solution.
There isn't a good answer, and the hugely upvoted answer in this thread is wrong.
npm install is-number
In JavaScript, it's not always as straightforward as it should be to reliably check if a value is a number. It's common for devs to use +, -, or Number() to cast a string value to a number (for example, when values are returned from user input, regex matches, parsers, etc). But there are many non-intuitive edge cases that yield unexpected results:
console.log(+[]); //=> 0
console.log(+''); //=> 0
console.log(+' '); //=> 0
console.log(typeof NaN); //=> 'number'
Maybe this has been rehashed too many times, however I fought with this one today too and wanted to post my answer, as I didn't see any other answer that does it as simply or thoroughly:
var isNumeric = function(num){
return (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num);
}
const isNumeric = (num) => (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num);
const isNumeric = (num: any) => (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num as number);
This seems quite simple and covers all the bases I saw on the many other posts and thought up myself:
// Positive Cases
console.log(0, isNumeric(0) === true);
console.log(1, isNumeric(1) === true);
console.log(1234567890, isNumeric(1234567890) === true);
console.log('1234567890', isNumeric('1234567890') === true);
console.log('0', isNumeric('0') === true);
console.log('1', isNumeric('1') === true);
console.log('1.1', isNumeric('1.1') === true);
console.log('-1', isNumeric('-1') === true);
console.log('-1.2354', isNumeric('-1.2354') === true);
console.log('-1234567890', isNumeric('-1234567890') === true);
console.log(-1, isNumeric(-1) === true);
console.log(-32.1, isNumeric(-32.1) === true);
console.log('0x1', isNumeric('0x1') === true); // Valid number in hex
// Negative Cases
console.log(true, isNumeric(true) === false);
console.log(false, isNumeric(false) === false);
console.log('1..1', isNumeric('1..1') === false);
console.log('1,1', isNumeric('1,1') === false);
console.log('-32.1.12', isNumeric('-32.1.12') === false);
console.log('[blank]', isNumeric('') === false);
console.log('[spaces]', isNumeric(' ') === false);
console.log('null', isNumeric(null) === false);
console.log('undefined', isNumeric(undefined) === false);
console.log([], isNumeric([]) === false);
console.log('NaN', isNumeric(NaN) === false);
You can also try your own isNumeric
function and just past in these use cases and scan for "true" for all of them.
Or, to see the values that each return:
My solution:
// returns true for positive ints;
// no scientific notation, hexadecimals or floating point dots
var isPositiveInt = function(str) {
var result = true, chr;
for (var i = 0, n = str.length; i < n; i++) {
chr = str.charAt(i);
if ((chr < "0" || chr > "9") && chr != ",") { //not digit or thousands separator
result = false;
break;
};
if (i == 0 && (chr == "0" || chr == ",")) { //should not start with 0 or ,
result = false;
break;
};
};
return result;
};
You can add additional conditions inside the loop, to fit you particular needs.
You could make use of types, like with the flow library, to get static, compile time checking. Of course not terribly useful for user input.
// @flow
function acceptsNumber(value: number) {
// ...
}
acceptsNumber(42); // Works!
acceptsNumber(3.14); // Works!
acceptsNumber(NaN); // Works!
acceptsNumber(Infinity); // Works!
acceptsNumber("foo"); // Error!
2nd October 2020: note that many bare-bones approaches are fraught with subtle bugs (eg. whitespace, implicit partial parsing, radix, coercion of arrays etc.) that many of the answers here fail to take into account. The following implementation might work for you, but note that it does not cater for number separators other than the decimal point ".
":
function isNumeric(str) {
if (typeof str != "string") return false // we only process strings!
return !isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
!isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail
}
This works regardless of whether the variable content is a string or number.
isNaN(num) // returns true if the variable does NOT contain a valid number
isNaN(123) // false
isNaN('123') // false
isNaN('1e10000') // false (This translates to Infinity, which is a number)
isNaN('foo') // true
isNaN('10px') // true
Of course, you can negate this if you need to. For example, to implement the IsNumeric
example you gave:
function isNumeric(num){
return !isNaN(num)
}
Only works if the string only contains numeric characters, else it returns NaN
.
+num // returns the numeric value of the string, or NaN
// if the string isn't purely numeric characters
+'12' // 12
+'12.' // 12
+'12..' // NaN
+'.12' // 0.12
+'..12' // NaN
+'foo' // NaN
+'12px' // NaN
Useful for converting '12px' to 12, for example:
parseInt(num) // extracts a numeric value from the
// start of the string, or NaN.
parseInt('12') // 12
parseInt('aaa') // NaN
parseInt('12px') // 12
parseInt('foo2') // NaN These last two may be different
parseInt('12a5') // 12 from what you expected to see.
Bear in mind that, unlike +num
, parseInt
(as the name suggests) will convert a float into an integer by chopping off everything following the decimal point (if you want to use parseInt()
because of this behaviour, you're probably better off using another method instead):
+'12.345' // 12.345
parseInt(12.345) // 12
parseInt('12.345') // 12
Empty strings may be a little counter-intuitive. +num
converts empty strings or strings with spaces to zero, and isNaN()
assumes the same:
+'' // 0
+' ' // 0
isNaN('') // false
isNaN(' ') // false
But parseInt()
does not agree:
parseInt('') // NaN
parseInt(' ') // NaN