226

In Typescript, this shows an error saying isNaN accepts only numeric values

isNaN('9BX46B6A')

and this returns false because parseFloat('9BX46B6A') evaluates to 9

isNaN(parseFloat('9BX46B6A'))

I can still run with the error showing up in Visual Studio, but I would like to do it the right way.

Currently, I have written this modified function -

static isNaNModified = (inputStr: string) => {
    var numericRepr = parseFloat(inputStr);
    return isNaN(numericRepr) || numericRepr.toString().length != inputStr.length;
}
user3509546
  • 2,397
  • 2
  • 9
  • 8
  • Possible duplicate of [TypeScript Converting a String to a number](http://stackoverflow.com/questions/14667713/typescript-converting-a-string-to-a-number) – Wesley Coetzee Jun 27 '16 at 07:31

11 Answers11

405

The way to convert a string to a number is with Number, not parseFloat.

Number('1234') // 1234
Number('9BX9') // NaN

You can also use the unary plus operator if you like shorthand:

+'1234' // 1234
+'9BX9' // NaN

Be careful when checking against NaN (the operator === and !== don't work as expected with NaN). Use:

 isNaN(+maybeNumber) // returns true if NaN, otherwise false
C Snover
  • 15,265
  • 4
  • 26
  • 38
  • 20
    does that mean that doing this: if (isNaN(+possibleNumberString)) is a valid way of checking? – Mathijs Segers Feb 12 '16 at 10:30
  • 7
    Why would you use `Number` above `parseInt` or `parseFloat`? `Number('')` gives 0 while `parseInt('')` gives `NaN` which is more in line to what I expect. – Didii Oct 27 '17 at 14:48
  • 9
    As mentioned *in the original question*, `parseInt('9BX9')` (and `parseFloat('9BX9')`) will return `9`, not `NaN`. If you don’t want the conversion of an empty string to 0, check explicitly for empty string first. – C Snover Oct 28 '17 at 00:11
  • pay attention: NaN is a number but NaN === NaN and NaN == NaN always are false, https://stackoverflow.com/questions/2801601/why-does-typeof-nan-return-number – Ging3r Feb 13 '18 at 10:47
  • 1
    If you want to check for it, use `isNaN(Number(what_ever))` instead of `Number(what_ever) === Nan`. – k0pernikus Feb 13 '18 at 14:15
  • Can anyone point me to the documentation for `Number('1234')` ? I'm looking through https://www.typescriptlang.org/docs/handbook/ but I can't find it, and I don't know what kind of function it is so I don't know what to search for - but I'd like to learn more. Thanks! – sauntimo Jan 12 '19 at 23:41
  • 3
    @sauntimo `Number` is not a TypeScript thing, it is a [built-in EcmaScript constructor function](https://www.ecma-international.org/ecma-262/6.0/#sec-number-constructor) which accepts a value and returns a number primitive when called as a function rather than a constructor. – C Snover Jan 18 '19 at 00:43
  • @CSnover ah, thank you - just what I needed. Much obliged! – sauntimo Jan 18 '19 at 07:01
  • There is one more side to this. If you use Number('1234') then you can't directly use + (for sum) e.g. `Number('1') + Number('2')` will return compile time error as typescript doesn't allows use of + operator between two Number types. However the unary operator '+' is much better and convenient to use in such use cases i.e. `(+('1')) + (+('1'))` would compile just fine. – Praveen Jan 31 '19 at 11:54
  • @Invoker Nope. `Number('1') + Number('2')` is a valid expression in TypeScript. If you are experiencing an error, you’re probably calling the Number constructor with `new`, which creates a `Number` object instead of a `number` primitive. – C Snover Feb 06 '19 at 16:47
  • Actually, it also returns an error if you have two class properties of type Number and try to add their values as even when you didn't explicitly used the `new` keyword to declare the property. Although you are correct that `Number('1') + Number('1')` may not return an error in this case but it doesn't rule out the possibility of other cases where someone tries to add two properties of Number type. Just saying that using unary `+` operator is much more reliable as mentioned in your post. Here is a [link](https://github.com/Microsoft/TypeScript/issues/2031) where these cases are discussed. – Praveen Feb 07 '19 at 17:58
  • 1
    @Invoker `Number('1')` will generate the same type and value as `+'1'` no matter what. Your assertion that the unary `+` operator is “much more reliable” in this case is wrong. Your problem is an unrelated bug where you’ve used `Number`, which is the object type, instead of `number`, which is the primitive type. TypeScript doesn’t allow implicit conversion to the primitive type in order to perform an arithmetic operation. It has nothing to do with this question, or this answer. – C Snover Feb 08 '19 at 22:23
  • Use isNaN(string) does not work anymore, you receive this error `TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.` – danielbchaves Sep 28 '20 at 09:21
53

Update 2

This method is no longer available in rxjs v6

I'm solved it by using the isNumeric operator from rxjs library (importing rxjs/util/isNumeric

Update

import { isNumeric } from 'rxjs/util/isNumeric';

. . .

var val = "5700";
if (isNumeric(val)){
   alert("it is number !");
}
Community
  • 1
  • 1
Richard Lee
  • 1,673
  • 1
  • 21
  • 29
45
function isNumber(value: string | number): boolean
{
   return ((value != null) &&
           (value !== '') &&
           !isNaN(Number(value.toString())));
}
Gil Epshtain
  • 5,688
  • 5
  • 42
  • 67
5

You can use the Number.isFinite() function:

Number.isFinite(Infinity);  // false
Number.isFinite(NaN);       // false
Number.isFinite(-Infinity); // false
Number.isFinite('0');       // false
Number.isFinite(null);      // false

Number.isFinite(0);         // true
Number.isFinite(2e64);      // true

Note: there's a significant difference between the global function isFinite() and the latter Number.isFinite(). In the case of the former, string coercion is performed - so isFinite('0') === true whilst Number.isFinite('0') === false.

Also, note that this is not available in IE!

James Paterson
  • 1,994
  • 2
  • 23
  • 32
  • But...TS2345: Argument of type '"1"' is not assignable to parameter of type 'number'. It it needs to be Number.isFinite(Number('0')); – Mcgri Jun 07 '20 at 09:49
4

I would choose an existing and already tested solution. For example this from rxjs in typescript:

function isNumeric(val: any): val is number | string {
  // parseFloat NaNs numeric-cast false positives (null|true|false|"")
  // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
  // subtraction forces infinities to NaN
  // adding 1 corrects loss of precision from parseFloat (#15100)
  return !isArray(val) && (val - parseFloat(val) + 1) >= 0;
}

rxjs/isNumeric.ts

Without rxjs isArray() function and with simplefied typings:

function isNumeric(val: any): boolean {
  return !(val instanceof Array) && (val - parseFloat(val) + 1) >= 0;
}

You should always test such functions with your use cases. If you have special value types, this function may not be your solution. You can test the function here.

Results are:

enum         : CardTypes.Debit   : true
decimal      : 10                : true
hexaDecimal  : 0xf10b            : true
binary       : 0b110100          : true
octal        : 0o410             : true
stringNumber : '10'              : true

string       : 'Hello'           : false
undefined    : undefined         : false
null         : null              : false
function     : () => {}          : false
array        : [80, 85, 75]      : false
turple       : ['Kunal', 2018]   : false
object       : {}                : false

As you can see, you have to be careful, if you use this function with enums.

Jan
  • 293
  • 2
  • 13
4

Simple answer: (watch for blank & null)

isNaN(+'111') = false;
isNaN(+'111r') = true;
isNaN(+'r') = true;
isNaN(+'') = false;   
isNaN(null) = false;   

https://codepen.io/CQCoder/pen/zYGEjxd?editors=1111

Nick H
  • 301
  • 4
  • 8
2

For full numbers (non-floats) in Angular you can use:

if (Number.isInteger(yourVariable)) { ... }

Felix
  • 1,102
  • 1
  • 8
  • 20
  • 3
    `Number.isInteger` just tells you if `yourVariable`, which is already a `number` type, is an integer. Does not work with strings. So, `Number.isInteger(Number(yourVariable))` might do the trick. – tarrball Feb 18 '20 at 13:09
1

Most of the time the value that we want to check is string or number, so here is function that i use:

const isNumber = (n: string | number): boolean => 
    !isNaN(parseFloat(String(n))) && isFinite(Number(n));

Codesandbox tests.

const willBeTrue = [0.1, '1', '-1', 1, -1, 0, -0, '0', "-0", 2e2, 1e23, 1.1, -0.1, '0.1', '2e2', '1e23', '-0.1', ' 898', '080']

const willBeFalse = ['9BX46B6A', "+''", '', '-0,1', [], '123a', 'a', 'NaN', 1e10000, undefined, null, NaN, Infinity, () => {}]
ZiiMakc
  • 13,102
  • 10
  • 32
  • 60
1

My simple solution here is:

const isNumeric = (val: string) : boolean => {
   return !isNaN(Number(val));
}

// isNumberic("2") => true
// isNumeric("hi") => false;
Hung Vu
  • 4,698
  • 2
  • 22
  • 25
-1

if var sum=0; var x;

then, what about this? sum+=(x|0);

-4

Whether a string can be parsed as a number is a runtime concern. Typescript does not support this use case as it is focused on compile time (not runtime) safety.

Rick
  • 1,066
  • 1
  • 18
  • 26
basarat
  • 207,493
  • 46
  • 386
  • 462