.map(parseInt) does not do what it says on the tin
The Context
Writing a script for a pre-push hook which uses a PowerShell script to check for occurrences of certain strings (e.g.
@ts-ignore
and @ts-expect-error
) being removed from the codebase. We can then gamify tech quality! ✨I’m running the PowerShell script from JavaScript with execSync. The PowerShell script returns a comma separated list of string numbers (e.g.
['1']
). In processing this list, I ran into an issue that I had experienced a while ago, but forgot about when trying to convert to a list of numbers using .map(parseInt)
. The Problem
const strArr = ['2', '2', '1', '1']; const intArr = strArr.map(parseInt); console.log(intArr); // >> [2, NaN, 1, 1]
I initially expected the output of this (from reading the syntax) to be
[2, 2, 1, 1]
.The Solution
The API for parseInt, specifies that the parameters it takes are:
string
A string starting with an integer. Leading whitespace in this argument is ignored.radix
OptionalAn integer between2
and36
that represents the radix (the base in mathematical numeral systems) of thestring
. It is converted to a 32-bit integer; if it's nonzero and outside the range of [2, 36] after conversion, the function will always returnNaN
. If0
or not provided, the radix will be inferred based onstring
's value. Be careful — this does not always default to10
! The description below explains in more detail what happens whenradix
is not provided.
element
The current element being processed in the array.index
The index of the current element being processed in the array.array
The arraymap()
was called upon.
This means that my original code is the equivalent of:
const intArr = strArr.map((...args) => parseInt(...args)); const intArr = strArr.map((element, index, array) => parseInt(element, index, array));
Which passes through the
index
from map
as the optional radix
parameter in parseInt
.The Fix (easy)
// Fixed const intArr = strArr.map((element) => parseInt(element));