Files
scriptc/tests/corpus/7185-array-callback-arguments-length.ts
T
Chris Tate 8aac437ed2 Keep reduce accumulators and callback argument counts as Node runs them
Array reduce typed its accumulator by the call's checked type, widened
with undefined only when the callback could return a missing value or a
receiver without an initial value could have holes. Three runtime values
fell outside it and threw "not representable in the target union":

- an initial value read from a missing element;
- a callback result of another primitive (`missing[0] ?? "fallback"`);
- a callback wrapped in parentheses, which the analysis and the callback
  lowering did not see as the arrow it wraps.

The accumulator now also takes undefined from a possibly missing initial
value, and the primitive arms the callback's result can have. Array
callbacks are taken without their parentheses.

`arguments.length` in a fixed-arity function expression folded to its
declared parameter count. When the expression flows into a fixed-arity
function type with more parameters, as array callbacks do (value, index,
array, and the accumulator for reduce), every call passes that type's
count, and the length is that count.
2026-10-22 08:53:50 -05:00

43 lines
1.1 KiB
TypeScript

// `arguments.length` in a function-expression callback counts every
// argument the array method passes: value, index and array, plus the
// accumulator for reduce. One stored in a fixed-arity function type counts
// that type's parameters, which every call passes.
const seen: number[] = [];
[10, 20].forEach(function (value) {
seen.push(arguments.length, value);
});
console.log(seen.join(","));
console.log(
[1, 2]
.map(function (value) {
return `${value}:${arguments.length}`;
})
.join(" "),
);
console.log([5].filter(function () {
return arguments.length === 3;
}).length);
console.log([1].reduce(function (acc, value) {
return acc + value + arguments.length;
}, 0));
console.log(["x", "y"].reduceRight(function (acc: string, value: string) {
return `${acc}${value}${arguments.length}`;
}, ""));
console.log([3, 4].some(function (value) {
return arguments.length === 3 && value === 4;
}));
const sum: (a: number, b: number) => number = function (a) {
return a + arguments.length;
};
console.log(sum(1, 2));
console.log([3, 1, 2].sort(function (a, b) {
return arguments.length === 2 ? a - b : 0;
}).join(","));