Converting a JavaScript array of strings to numbers, and the problem with `Array.map`
2021 March 15

JavaScript has a very weird type system with how strings can sometimes be converted to numbers. It’s a very cool feature but can cause a lot of pain because adding 1 doesn’t always do what you think it should due to type-juggling. So you might think there’s an easy and relatively foot-gun free to convert an array of strings to numbers. You would be wrong, well maybe not at least if you don’t use the functional language stuff in JavaScript or just do an in-place update or your array, but that’s besides the point.

Here’s a simple example. The variable x has a list of strings 1, 2, 3 assigned to it. If the array has parseInt applied to it via Array.map. What is expected to happen? You would expect that the strings would be parsed using their base 10 representations. Well that’s not what happens.

x = ["1", "2", "3"]
x.map(parseInt); // [1, NaN, NaN]

The problem is the callback that Array.map expects, and how JavaScript handles function arguments. If you look at MDN, the expected callback looks like so:

function myAppliedFunc(currentValue, index, theArray) { /* .. */ }

So if I pass in the raw parseInt function, which takes in 2 parameters the string and an optional radix. The index is received as the radix to use. So for the 2nd element ‘2’, it sees a 1 radix because of counting from zero. ‘2’ is not a valid digit in a base 1 system only zero. So JavaScript is helpful and returns NaN, instead of returning a proper error. Completely valid decision, just a really irritating one not to be caught by a linter. It’s a problem with being over-flexible. It’s just that we were not expecting that. Maybe parseInt could have thrown an error when the radix got too big for it to handle, but then again exceptions really suck.

So the correct way is to curry parseInt and fill in the 2nd parameter with what base your strings are in.

['1', '2', '3', '4'].map((x) => parseInt(x, 10))

The even more correct way is to use the Number function instead, as show below (Thanks Dr. Killian):

['1', '2', '3'].map(Number)

Feel free to email me about any weird JavaScript issues or foot guns you’ve found.

*****
Written by Henry J Schmale on 2021 March 15