This site has been updated.

# Test whether variable is a number

July 18, 2020

The post title “Test whether variable is a number” looks like a trivial question, but let’s dig deeper and try to cover all edge cases. I will split it into two problems and will cover them separately.

## isNumber

First I’ll start with the simple problem. You have variable that may or may not be a number. Write a function `isNumber()` that will return `true` if it is in fact ‘number’ or `false` otherwise.

Here I only need to check the type of given variable. In this situation I have two edge cases.

The first one is `NaN`, which has a `number` type, but is not a meaningful number, since I can’t use it in any calculation. And it’s up to the developer to decide how to handle this situation. By the way `lodash/isNumber` is not covering `NaN` case and will return `true` for `NaN`. Which is technically correct, but still I prefer not to call it a number.

The second edge case is not frequent, but since JS allows it, we will cover it as well. User has additional way to define a number, by using `Number` as a constructor, like this:

``const num = new Number(2);``

In this case the type of `num` variable will be an `object`, when in fact it will act as a number in all other cases. So we need to check for that as well.

``````function isNumber(value) {
// `isNaN` is build in global function, that is supported since IE6
// (Since ES6, we also have `Number.isNaN` method which make more since, then global function)
if (isNaN(value)) {
return false;
}
if (value instanceof Number) {
return true;
}
return typeof value === 'number';
}``````

Ok, now let’s see the test cases:

``````console.assert(isNumber(2) === true, 'should validate regular number');
console.assert(isNumber('true') === false, 'should validate string');
console.assert(isNumber('7') === false, 'should validate string as number');
console.assert(isNumber(NaN) === false, 'should validate NaN');
console.assert(isNumber(Number(10)) === true, 'should validate Number');
console.assert(isNumber(new Number(5)) === true, 'should validate Number constructor');
console.assert(isNumber(true) === false, 'should validate boolean');``````

## couldBeNumber

Now let’s solve a more complicated case, that is related to types magic of JS.

You have a variable that may or may not be a number, but it can be converted to a number in the meaningful way. For example string ‘2’ can be converted to number 2, but boolean `true` cannot. Write a function `couldBeNumber()` that will return `true` if it is in fact number or `false` otherwise.

``````function couldBeNumber(value) {
// First lets check whether given value is a string.
// Here I'm also covering the case when value defined via constructor `new String()`.
const isString = typeof value === 'string' || value instanceof String;
// If the user gave us a string, then we need to check whether it's empty.
// Since string can be created with `String` constructor I need to cast it to the regular string,
// therefore I'm doing `value + ''` (otherwise I can't compare it to an empty string).
// By the way, I need to check for an empty string, since `Number('')` will return `0`.
// And I'm using `Number` in the first place since this way I can cover integers
// and floats with one conversion method.
if (isString && value + '' !== '') {
// `Number()` of something that can't be converted to number will return `NaN` and
// by specification of ECMAScript `NaN` not equal to `NaN`.
// Therefore I can just compare it to itself.
return Number(value) === Number(value);
}
// In the end I can just use the previously defined `isNumber()` function.
return isNumber(value);
}``````

Now let’s see the test cases. Half of them are covered in the first part of this post, but I prefer to copy them over here as well.

``````console.assert(couldBeNumber('1') === true, 'should validate string as a number (integer)');
console.assert(couldBeNumber('1.2') === true, 'should validate string as a number (float)');
console.assert(couldBeNumber('-1.2') === true, 'should validate string as a number (negative float)');
console.assert(couldBeNumber(new String('5')) === true, 'should validate string as a number (String constructor)');
console.assert(couldBeNumber('') === false, 'should validate empty string');
console.assert(couldBeNumber('a') === false, 'should validate string');
console.assert(couldBeNumber(2) === true, 'should validate regular number');
console.assert(couldBeNumber(NaN) === false, 'should validate NaN');
console.assert(couldBeNumber(Number(10)) === true, 'should validate Number');
console.assert(couldBeNumber(new Number(5)) === true, 'should validate Number constructor');
console.assert(couldBeNumber(true) === false, 'should validate boolean');``````