(Built-in) way in JavaScript to check if a string is a valid number


I'm hoping there's something in the same conceptual space as the old VB6 IsNumeric() function?

To check if a variable (including a string) is a number, check if it is not a number:

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

Examples

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)
}

To convert a string containing a number into a number:

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

Examples

+'12'              // 12
+'12.'             // 12
+'12..'            // Nan
+'.12'             // 0.12
+'..12'            // Nan
+'foo'             // NaN
+'12px'            // NaN

To convert a string loosely to a number

Useful for converting '12px' to 12, for example:

parseInt(num)      // extracts a numeric value from the 
                   // start of the string, or NaN.

Examples

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. 

Floats

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

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

And you could go the RegExp-way:

var num = "987238";

if(num.match(/^-{0,1}\d+$/)){
  //valid integer (positive or negative)
}else if(num.match(/^\d+\.\d+$/)){
  //valid float
}else{
  //not valid number
}

If you're just trying to check if a string is a whole number (no decimal places), regex is a good way to go. Other methods such as isNaN are too complicated for something so simple.

function isNumeric(value) {
    return /^-{0,1}\d+$/.test(value);
}

console.log(isNumeric('abcd'));         // false
console.log(isNumeric('123a'));         // false
console.log(isNumeric('1'));            // true
console.log(isNumeric('1234567890'));   // true
console.log(isNumeric('-23'));          // true
console.log(isNumeric(1234));           // true
console.log(isNumeric('123.4'));        // false
console.log(isNumeric(''));             // false
console.log(isNumeric(undefined));      // false
console.log(isNumeric(null));           // false

To only allow positive whole numbers use this:

function isNumeric(value) {
    return /^\d+$/.test(value);
}

console.log(isNumeric('123'));          // true
console.log(isNumeric('-23'));          // false

If you really want to make sure that a string contains only a number, any number (integer or floating point), and exactly a number, you cannot use parseInt()/ parseFloat(), Number(), or !isNaN() by themselves. Note that !isNaN() is actually returning true when Number() would return a number, and false when it would return NaN, so I will exclude it from the rest of the discussion.

The problem with parseFloat() is that it will return a number if the string contains any number, even if the string doesn't contain only and exactly a number:

parseFloat("2016-12-31")  // returns 2016
parseFloat("1-1") // return 1
parseFloat("1.2.3") // returns 1.2

The problem with Number() is that it will return a number in cases where the passed value is not a number at all!

Number("") // returns 0
Number(" ") // returns 0
Number(" \u00A0   \t\n\r") // returns 0

The problem with rolling your own regex is that unless you create the exact regex for matching a floating point number as Javascript recognizes it you are going to miss cases or recognize cases where you shouldn't. And even if you can roll your own regex, why? There are simpler built-in ways to do it.

However, it turns out that Number() (and isNaN()) does the right thing for every case where parseFloat() returns a number when it shouldn't, and vice versa. So to find out if a string is really exactly and only a number, call both functions and see if they both return true:

function isNumber(str) {
  if (typeof str != "string") return false // we only process strings!
  // could also coerce to string: str = ""+str
  return !isNaN(str) && !isNaN(parseFloat(str))
}

The accepted answer for this question has quite a few flaws (as highlighted by couple of other users). This is one of the easiest & proven way to approach it in javascript:

function isNumeric(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

Below are some good test cases:

console.log(isNumeric(12345678912345678912)); // true
console.log(isNumeric('2 '));                 // true
console.log(isNumeric('-32.2 '));             // true
console.log(isNumeric(-32.2));                // true
console.log(isNumeric(undefined));            // false

// the accepted answer fails at these tests:
console.log(isNumeric(''));                   // false
console.log(isNumeric(null));                 // false
console.log(isNumeric([]));                   // false

Try the isNan function:

The isNaN() function determines whether a value is an illegal number (Not-a-Number).

This function returns true if the value equates to NaN. Otherwise it returns false.

This function is different from the Number specific Number.isNaN() method.

  The global isNaN() function, converts the tested value to a Number, then tests it.

Number.isNan() does not convert the values to a Number, and will not return true for any value that is not of the type Number...


Old question, but there are several points missing in the given answers.

Scientific notation.

!isNaN('1e+30') is true, however in most of the cases when people ask for numbers, they do not want to match things like 1e+30.

Large floating numbers may behave weird

Observe (using Node.js):

> var s = Array(16 + 1).join('9')
undefined
> s.length
16
> s
'9999999999999999'
> !isNaN(s)
true
> Number(s)
10000000000000000
> String(Number(s)) === s
false
>

On the other hand:

> var s = Array(16 + 1).join('1')
undefined
> String(Number(s)) === s
true
> var s = Array(15 + 1).join('9')
undefined
> String(Number(s)) === s
true
>

So, if one expects String(Number(s)) === s, then better limit your strings to 15 digits at most (after omitting leading zeros).

Infinity

> typeof Infinity
'number'
> !isNaN('Infinity')
true
> isFinite('Infinity')
false
>

Given all that, checking that the given string is a number satisfying all of the following:

  • non scientific notation
  • predictable conversion to Number and back to String
  • finite

is not such an easy task. Here is a simple version:

  function isNonScientificNumberString(o) {
    if (!o || typeof o !== 'string') {
      // Should not be given anything but strings.
      return false;
    }
    return o.length <= 15 && o.indexOf('e+') < 0 && o.indexOf('E+') < 0 && !isNaN(o) && isFinite(o);
  }

However, even this one is far from complete. Leading zeros are not handled here, but they do screw the length test.


I have tested and Michael's solution is best. Vote for his answer above (search this page for "If you really want to make sure that a string" to find it). In essence, his answer is this:

function isNumeric(num){
  num = "" + num; //coerce num to be a string
  return !isNaN(num) && !isNaN(parseFloat(num));
}

It works for every test case, which I documented here: https://jsfiddle.net/wggehvp9/5/

Many of the other solutions fail for these edge cases: ' ', null, "", true, and []. In theory, you could use them, with proper error handling, for example:

return !isNaN(num);

or

return (+num === +num);

with special handling for /\s/, null, "", true, false, [] (and others?)


You can use the result of Number when passing an argument to its constructor.

If the argument (a string) cannot be converted into a number, it returns NaN, so you can determinate if the string provided was a valid number or not.

Notes: Note when passing empty string or '\t\t' and '\n\t' as Number will return 0; Passing true will return 1 and false returns 0.

    Number('34.00') // 34
    Number('-34') // -34
    Number('123e5') // 12300000
    Number('123e-5') // 0.00123
    Number('999999999999') // 999999999999
    Number('9999999999999999') // 10000000000000000 (integer accuracy up to 15 digit)
    Number('0xFF') // 255
    Number('Infinity') // Infinity  

    Number('34px') // NaN
    Number('xyz') // NaN
    Number('true') // NaN
    Number('false') // NaN

    // cavets
    Number('    ') // 0
    Number('\t\t') // 0
    Number('\n\t') // 0

Maybe there are one or two people coming across this question who need a much stricter check than usual (like I did). In that case, this might be useful:

if(str === String(Number(str))) {
  // it's a "perfectly formatted" number
}

Beware! This will reject strings like .1, 40.000, 080, 00.1. It's very picky - the string must match the "most minimal perfect form" of the number for this test to pass.

It uses the String and Number constructor to cast the string to a number and back again and thus checks if the JavaScript engine's "perfect minimal form" (the one it got converted to with the initial Number constructor) matches the original string.


parseInt(), but be aware that this function is a bit different in the sense that it for example returns 100 for parseInt("100px").


Quote:

isNaN(num) // returns true if the variable does NOT contain a valid number

is not entirely true if you need to check for leading/trailing spaces - for example when a certain quantity of digits is required, and you need to get, say, '1111' and not ' 111' or '111 ' for perhaps a PIN input.

Better to use:

var num = /^\d+$/.test(num)

Why is jQuery's implementation not good enough?

function isNumeric(a) {
    var b = a && a.toString();
    return !$.isArray(a) && b - parseFloat(b) + 1 >= 0;
};

Michael suggested something like this (although I've stolen "user1691651 - John"'s altered version here):

function isNumeric(num){
    num = "" + num; //coerce num to be a string
    return !isNaN(num) && !isNaN(parseFloat(num));
}

The following is a solution with most likely bad performance, but solid results. It is a contraption made from the jQuery 1.12.4 implementation and Michael's answer, with an extra check for leading/trailing spaces (because Michael's version returns true for numerics with leading/trailing spaces):

function isNumeric(a) {
    var str = a + "";
    var b = a && a.toString();
    return !$.isArray(a) && b - parseFloat(b) + 1 >= 0 &&
           !/^\s+|\s+$/g.test(str) &&
           !isNaN(str) && !isNaN(parseFloat(str));
};

The latter version has two new variables, though. One could get around one of those, by doing:

function isNumeric(a) {
    if ($.isArray(a)) return false;
    var b = a && a.toString();
    a = a + "";
    return b - parseFloat(b) + 1 >= 0 &&
            !/^\s+|\s+$/g.test(a) &&
            !isNaN(a) && !isNaN(parseFloat(a));
};

I haven't tested any of these very much, by other means than manually testing the few use-cases I'll be hitting with my current predicament, which is all very standard stuff. This is a "standing-on-the-shoulders-of-giants" situation.


It is not valid for TypeScript as:

declare function isNaN(number: number): boolean;

For TypeScript you can use:

/^\d+$/.test(key)


Well, I'm using this one I made...

It's been working so far:

function checkNumber(value) {
    if ( value % 1 == 0 )
    return true;
    else
    return false;
}

If you spot any problem with it, tell me, please.


If anyone ever gets this far down, I spent some time hacking on this trying to patch moment.js (https://github.com/moment/moment). Here's something that I took away from it:

function isNumeric(val) {
    var _val = +val;
    return (val !== val + 1) //infinity check
        && (_val === +val) //Cute coercion check
        && (typeof val !== 'object') //Array/object check
}

Handles the following cases:

True! :

isNumeric("1"))
isNumeric(1e10))
isNumeric(1E10))
isNumeric(+"6e4"))
isNumeric("1.2222"))
isNumeric("-1.2222"))
isNumeric("-1.222200000000000000"))
isNumeric("1.222200000000000000"))
isNumeric(1))
isNumeric(0))
isNumeric(-0))
isNumeric(1010010293029))
isNumeric(1.100393830000))
isNumeric(Math.LN2))
isNumeric(Math.PI))
isNumeric(5e10))

False! :

isNumeric(NaN))
isNumeric(Infinity))
isNumeric(-Infinity))
isNumeric())
isNumeric(undefined))
isNumeric('[1,2,3]'))
isNumeric({a:1,b:2}))
isNumeric(null))
isNumeric([1]))
isNumeric(new Date()))

Ironically, the one I am struggling with the most:

isNumeric(new Number(1)) => false

Any suggestions welcome. :]


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 ...
}

2019: Practical and tight numerical validity check

Often, a 'valid number' means a Javascript number excluding NaN and Infinity, ie a 'finite number'.

To check the numerical validity of a value (from an external source for example), you can define in ESlint Airbnb style :

/**
 * Returns true if 'candidate' is a finite number or a string referring (not just 'including') a finite number
 * To keep in mind:
 *   Number(true) = 1
 *   Number('') = 0
 *   Number("   10  ") = 10
 *   !isNaN(true) = true
 *   parseFloat('10 a') = 10
 *
 * @param {?} candidate
 * @return {boolean}
 */
function isReferringFiniteNumber(candidate) {
  if (typeof (candidate) === 'number') return Number.isFinite(candidate);
  if (typeof (candidate) === 'string') {
    return (candidate.trim() !== '') && Number.isFinite(Number(candidate));
  }
  return false;
}

and use it this way:

if (isReferringFiniteNumber(theirValue)) {
  myCheckedValue = Number(theirValue);
} else {
  console.warn('The provided value doesn\'t refer to a finite number');
}

PFB the working solution:

 function(check){ 
    check = check + "";
    var isNumber =   check.trim().length>0? !isNaN(check):false;
    return isNumber;
    }

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'

Using plain JavaScript:

Number.isNaN(Number('1')); // false
Number.isNaN(Number('asdf')); // true

Using Lodash:

_.isNaN(_.toNumber('1')); // false
_.isNaN(_.toNumber('asdf')); // true

I recently wrote an article about ways to ensure a variable is a valid number: https://github.com/jehugaleahsa/artifacts/blob/master/2018/typescript_num_hack.md The article explains how to ensure floating point or integer, if that's important (+x vs ~~x).

The article assumes the variable is a string or a number to begin with and trim is available/polyfilled. It wouldn't be hard to extend it to handle other types, as well. Here's the meat of it:

// Check for a valid float
if (x == null
    || ("" + x).trim() === ""
    || isNaN(+x)) {
    return false;  // not a float
}

// Check for a valid integer
if (x == null
    || ("" + x).trim() === ""
    || ~~x !== +x) {
    return false;  // not an integer
}

2019: Including ES3, ES6 and TypeScript Examples

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:

ES3

var isNumeric = function(num){
    return (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num);  
}

ES6

const isNumeric = (num) => (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num);

Typescript

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:

Results of each test against <code>isNumeric()</code>


My attempt at a slightly confusing, Pherhaps not the best solution

function isInt(a){
    return a === ""+~~a
}


console.log(isInt('abcd'));         // false
console.log(isInt('123a'));         // false
console.log(isInt('1'));            // true
console.log(isInt('0'));            // true
console.log(isInt('-0'));           // false
console.log(isInt('01'));           // false
console.log(isInt('10'));           // true
console.log(isInt('-1234567890'));  // true
console.log(isInt(1234));           // false
console.log(isInt('123.4'));        // false
console.log(isInt(''));             // false

// other types then string returns false
console.log(isInt(5));              // false
console.log(isInt(undefined));      // false
console.log(isInt(null));           // false
console.log(isInt('0x1'));          // false
console.log(isInt(Infinity));       // false

In my application we are only allowing a-z A-Z and 0-9 characters. I found the answer above using " string % 1 === 0" worked unless the string began with 0xnn (like 0x10) and then it would return it as numeric when we didn't want it to. The following simple trap in my numeric check seems to do the trick in our specific cases.

function isStringNumeric(str_input){   
    //concat a temporary 1 during the modulus to keep a beginning hex switch combination from messing us up   
    //very simple and as long as special characters (non a-z A-Z 0-9) are trapped it is fine   
    return '1'.concat(str_input) % 1 === 0;}

Warning : This might be exploiting a longstanding bug in Javascript and Actionscript [Number("1" + the_string) % 1 === 0)], I can't speak for that, but it is exactly what we needed.


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!

Here's a one-liner to check if sNum is a valid numeric value; it has been tested for a wide variety of inputs:

!isNaN(+s.replace(/\s|\$/g, ''));  // returns True if numeric value

Just use isNaN(), this will convert the string to a number and if get a valid number, will return false...

isNaN("Alireza"); //return true
isNaN("123"); //return false

I'm using the following:

const isNumber = s => !isNaN(+s)

This appears to catch the seemingly infinite number of edge cases:

function isNumber(x, noStr) {
    /*

        - Returns true if x is either a finite number type or a string containing only a number
        - If empty string supplied, fall back to explicit false
        - Pass true for noStr to return false when typeof x is "string", off by default

        isNumber(); // false
        isNumber([]); // false
        isNumber([1]); // false
        isNumber([1,2]); // false
        isNumber(''); // false
        isNumber(null); // false
        isNumber({}); // false
        isNumber(true); // false
        isNumber('true'); // false
        isNumber('false'); // false
        isNumber('123asdf'); // false
        isNumber('123.asdf'); // false
        isNumber(undefined); // false
        isNumber(Number.POSITIVE_INFINITY); // false
        isNumber(Number.NEGATIVE_INFINITY); // false
        isNumber('Infinity'); // false
        isNumber('-Infinity'); // false
        isNumber(Number.NaN); // false
        isNumber(new Date('December 17, 1995 03:24:00')); // false
        isNumber(0); // true
        isNumber('0'); // true
        isNumber(123); // true
        isNumber(123.456); // true
        isNumber(-123.456); // true
        isNumber(-.123456); // true
        isNumber('123'); // true
        isNumber('123.456'); // true
        isNumber('.123'); // true
        isNumber(.123); // true
        isNumber(Number.MAX_SAFE_INTEGER); // true
        isNumber(Number.MAX_VALUE); // true
        isNumber(Number.MIN_VALUE); // true
        isNumber(new Number(123)); // true
    */

    return (
        (typeof x === 'number' || x instanceof Number || (!noStr && x && typeof x === 'string' && !isNaN(x))) &&
        isFinite(x)
    ) || false;
};

This is built on some of the previous answers and comments. The following covers all the edge cases and fairly concise as well:

const isNumRegEx = /^-?(\d*\.)?\d+$/;

function isNumeric(n, allowScientificNotation = false) {
    return allowScientificNotation ? 
                !Number.isNaN(parseFloat(n)) && Number.isFinite(n) :
                isNumRegEx.test(n);
}

I used this function as a form validation tool, and I didn't want users to be able to write exponential function, so I came up with this function:

<script>

    function isNumber(value, acceptScientificNotation) {

        if(true !== acceptScientificNotation){
            return /^-{0,1}\d+(\.\d+)?$/.test(value);
        }

        if (true === Array.isArray(value)) {
            return false;
        }
        return !isNaN(parseInt(value, 10));
    }


    console.log(isNumber(""));              // false
    console.log(isNumber(false));           // false
    console.log(isNumber(true));            // false
    console.log(isNumber("0"));             // true
    console.log(isNumber("0.1"));           // true
    console.log(isNumber("12"));            // true
    console.log(isNumber("-12"));           // true
    console.log(isNumber(-45));             // true
    console.log(isNumber({jo: "pi"}));      // false
    console.log(isNumber([]));              // false
    console.log(isNumber([78, 79]));        // false
    console.log(isNumber(NaN));             // false
    console.log(isNumber(Infinity));        // false
    console.log(isNumber(undefined));       // false
    console.log(isNumber("0,1"));           // false



    console.log(isNumber("1e-1"));          // false
    console.log(isNumber("1e-1", true));    // true
</script>