.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:
stringA string starting with an integer. Leading whitespace in this argument is ignored.radixOptionalAn integer between2and36that 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. If0or 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 whenradixis not provided.
elementThe current element being processed in the array.indexThe index of the current element being processed in the array.arrayThe 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));