How to convert a string to a number in TypeScript
The solution
function stringToNumber(s: string): number | undefined {
const n = parseFloat(s)
if (Number.isNaN(n)) {
return undefined
}
return n
}
Why we need to do this
JavaScript has a function parseFloat() that converts strings into numbers.
> parseFloat('3')
3
> parseFloat('2.71828')
2.71828
parseFloat() may seem like a complete solution on its own, but there's a big problem here.
If we call parseFloat with something that's not a number, it will return NaN, which means "Not a Number".
> parseFloat('three')
NaN
Any operation on a NaN returns another NaN.
Unfortunately, that means that NaNs will propagate through our code, with every operation on them returning yet another NaN.
> parseFloat('a3') + 1
NaN
> 1 / (parseFloat('a3') + 1 * 20)
NaN
NaN is defined to be equal to nothing, not even itself.
That means we can't use the equality operator === to check for whether parseFloat() returned NaN.
> parseFloat('three') === NaN
false
Instead, we can check the result of parseFloat() with the Number.isNaN() function, which will tell us whether we actually parsed a number or not.
Number.isNaN() will return true if called on NaN.
> Number.isNaN(NaN)
true
> Number.isNaN(parseFloat('a3'))
true
> Number.isNaN(parseFloat('5'))
false
Now we've seen all of the components of our stringToNumber function.
It uses parseFloat to parse the string into a number, then Number.isNaN to make sure that it actually got a number out.
If the parse fails, it returns undefined.
function stringToNumber(s: string): number | undefined {
const n = parseFloat(s)
if (Number.isNaN(n)) {
return undefined
}
return n
}
This function parses numbers correctly!
> stringToNumber('3')
3
> stringToNumber('3.1415926')
3.1415926
It returns undefined when the result is not a number.
> stringToNumber('three')
undefined
> stringToNumber(null)
undefined
Type safety when parsing numbers
When we use this function, the TypeScript compiler makes us check for undefined before using the result as a number.
> stringToNumber('3') + 1;
type error: Object is possibly 'undefined'.
> const n = stringToNumber('3')
n !== undefined ? n + 1 : undefined
4
The TypeScript compiler won't let us pass in inputs that don't make sense, like non-string values.
> stringToNumber({});
type error: Argument of type '{}' is not assignable to parameter of type 'string'.