Act 1: What?!
import { describe, it, expect } from '@jest/globals';
describe("map parseInt over an array of strings", () => { it("should parse both numbers, but doesn't seem to", () => { expect(["0", "0"].map(parseInt)).toStrictEqual([0, 0]); });});The actual result is [0, NaN]. Huh.
Act 2: Hmmm…
import { describe, it, expect } from '@jest/globals';
describe("map parseInt over an array of strings", () => { it("should parse both numbers, but doesn't seem to", () => { expect(["0", "0"].map(s => parseInt(s))).toStrictEqual([0, 0]); expect(["0", "0"].map(parseInt)).toStrictEqual([0, NaN]); });});This test passes. Wait… when does eta-conversion fail?!
When there is more than one argument to the function we are “mapping”!
What does Array.map() actually do?
callback is called with three arguments: the value of the element, the index of the element, and the object being traversed.
--- https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.map
Act 3: Aha!
import { describe, it, expect } from '@jest/globals';
describe("map parseInt over an array of strings", () => { it("should parse both numbers, but doesn't seem to", () => { expect(["0", "0"].map(s => parseInt(s))).toStrictEqual([0, 0]); expect(["0", "0"].map(parseInt)).toStrictEqual([0, NaN]); expect(parseInt("0", 0, ["0", "0"])).toStrictEqual(0); expect(parseInt("0", 1, ["0", "0"])).toStrictEqual(NaN); // because radix != 0 and radix < 2 });});Since parseInt() interprets the index as a radix, and the radix is not 0 (where it would default to 10) and not 2 (which would result in interpreting the text as a binary number), the result is NaN. Obviously. (Read step 8.)
And that’s how we learn that eta-conversion with Array.map() in
TypeScript is special.
Epilogue
import { describe, it, expect } from '@jest/globals';
describe("map parseInt over an array of strings", () => { it("should parse both numbers, but doesn't seem to", () => { // Explicit parameter passing works as expected expect(["0", "0"].map(s => parseInt(s))).toStrictEqual([0, 0]);
// eta-conversion fails, because map() passes 3 arguments to the function, not only 1 expect(["0", "0"].map(parseInt)).toStrictEqual([0, NaN]);
// Notably, map() invokes callback(element, index, sourceObject), // but JavaScript/TypeScript can ignore superfluous arguments, which means... expect(parseInt("0", 0, ["0", "0"])).toStrictEqual(0); expect(parseInt("0", 1, ["0", "0"])).toStrictEqual(NaN); // because radix != 0 and radix < 2 });});