Skip to content

lib.es5.d.ts: accept array-likes (arguments, typed arrays, DOM collections) as the second argument of Function.prototype.apply#63654

Closed
KAMRONBEK wants to merge 1 commit into
microsoft:mainfrom
KAMRONBEK:fix/61835-apply-arraylike
Closed

lib.es5.d.ts: accept array-likes (arguments, typed arrays, DOM collections) as the second argument of Function.prototype.apply#63654
KAMRONBEK wants to merge 1 commit into
microsoft:mainfrom
KAMRONBEK:fix/61835-apply-arraylike

Conversation

@KAMRONBEK

Copy link
Copy Markdown

Fixes #61835

Summary

Function.prototype.apply accepts any array-like object as its second
argument, not just a real Array. This is normative in the ECMAScript spec:
Function.prototype.apply
builds its argument list with the abstract operation
CreateListFromArrayLike,
which reads the length property and the indexed properties 0 .. length-1
off an ordinary object — it never requires a genuine Array. MDN documents the
same: "You can also use any kind of object which is array-like as the second
parameter. In practice, this means that it needs to have a length property,
and integer ("index") properties … You can also use arguments."

Under strictBindCallApply (implied by strict), calls resolve to
CallableFunction.apply, whose second parameter is currently typed as the exact
tuple/array A extends any[]. That rejects perfectly valid array-likes that work
at runtime:

// @strict: true
const u8 = new Uint8Array([0x41, 0x42, 0x43]);
String.fromCharCode.apply(null, u8);
// ❌ before: Argument of type 'Uint8Array<ArrayBuffer>' is not assignable to
//    parameter of type 'number[]'.

const func: (...args: unknown[]) => void = function () {
  console.log.apply(null, arguments);
  // ❌ before: Argument of type 'IArguments' is not assignable to
  //    parameter of type 'any[]'.
};
func(1, 2, 3);

The only workaround today is Array.from(...), which the reporter correctly
notes imposes a needless runtime copy.

The fix

Add one overload to CallableFunction.apply in src/lib/es5.d.ts — the
existing tuple overload is left untouched:

apply<T, A extends any[], R, Args extends ArrayLike<A[number]>>(
    this: (this: T, ...args: A) => R,
    thisArg: T,
    args: Args extends readonly any[] ? A : Args,
): R;

Why an added overload and not a mutation of the existing one

Naively widening the existing overload's args: A to args: ArrayLike<A[number]>
regresses strictBindCallApply. That machinery relies on inferring the
argument tuple A and checking its arity and element types against the
parameter list. ArrayLike<T> has no length/arity, so cases that must error stop
erroring — verified empirically:

declare function foo(a: number, b: string): string;
foo.apply(undefined, [10]);              // must error (too few) — a plain ArrayLike widening SILENTLY ACCEPTS this
foo.apply(undefined, [10, 20]);          // must error (wrong type) — same
foo.apply(undefined, [10, "hello", 30]); // must error (too many) — same

Keeping the tuple overload first preserves precise arity checking for
arrays/tuples. But a plain ArrayLike fallback overload placed after it
re-introduces the same regression, because a tuple like [10] is assignable to
ArrayLike<number> and the fallback swallows it.

The discriminator

The added overload therefore routes on whether the supplied argument is a real
array/tuple:

  • Args extends readonly any[] — the input is an array or tuple (this holds
    for tuples and arrays, but not for Uint8Array, IArguments, or DOM
    collections, none of which are assignable to readonly any[]). The parameter
    type collapses to A, so the strict tuple check still applies and wrong-arity
    / wrong-type array literals still error exactly as before.
  • otherwise — the input is a non-array array-like, and the parameter type stays
    Args (constrained to ArrayLike<A[number]>), so Uint8Array, arguments,
    NodeList, etc. are accepted while an array-like of the wrong element type
    (e.g. ArrayLike<string> for a number parameter) is still rejected via the
    Args extends ArrayLike<A[number]> constraint.

This is why foo.apply(undefined, [10, 20]) still errors while
String.fromCharCode.apply(null, u8) type-checks.

Scope: CallableFunction only

NewableFunction.apply is deliberately left unchanged. Calling a constructor's
.apply invokes it as a plain function (not with new), which throws for real
classes at runtime, and no reported case targets it. The issue and all of its
examples (String.fromCharCode, console.log, arguments) are CallableFunction
calls. Keeping the change to CallableFunction.apply matches the reported surface
and avoids gratuitous churn. The non-strict Function.apply overload already
takes argArray?: any, so it was never affected.

Verification

Built the compiler (npx hereby local) and ran the full test battery with
the modified lib:

npx hereby runtests-parallel
→ 106377 passing (0 failing)

The lib change shifts a number of recorded baselines; each was reviewed and
hereby baseline-accepted. They fall into three buckets, all expected:

  1. The fix working — spurious IArguments/array-like errors on .apply
    removed, e.g. noParameterReassignmentJSIIFE (its .errors.txt is deleted
    because importScripts.apply(this, arguments) no longer errors),
    noParameterReassignmentIIFEAnnotated, argumentsReferenceInFunction1_Js.
  2. Errors preserved, message text widened — cases that still error now report
    via the "No overload matches this call" (TS2769) form because apply now has an
    extra overload (strictBindCallApply1, asyncArrowFunctionCapturesArguments_*,
    asyncFunctionDeclarationCapturesArguments_*, emitSkipsThisWithRestParameter).
    No error changed line or root cause; a zero-parameter target still rejects
    arguments because IArguments is not assignable to ArrayLike<never>.
  3. Cosmetic.types/.symbols baselines that print the apply signature
    now show the added overload. No .js emit baseline changed (a lib type
    change cannot affect emit, and none did).

A dedicated conformance fixture is added at
tests/cases/conformance/functions/applyArrayLike.ts proving both directions:
the array-like cases (Uint8Array, arguments, ArrayLike<number>) type-check,
and the arity / wrong-element-type cases still error.

Known trade-off (for maintainer review)

The one real downside is diagnostic verbosity: because apply now carries an
extra overload, a genuinely wrong apply call reports the multi-line
TS2769: No overload matches this call. form instead of the previous crisp
single TS2345/TS2322. Correctness of type-checking is unchanged — only the
error presentation is noisier. If the team prefers to preserve the terse
diagnostics, an alternative is to gate the array-like acceptance behind a compiler
change rather than a purely-declarative overload, but that is a larger change; the
declarative overload here is the minimal fix that resolves the reported cases with
no semantic regression.

Files changed

  • src/lib/es5.d.ts — add the array-like apply overload to CallableFunction.
  • tests/cases/conformance/functions/applyArrayLike.ts — new conformance fixture.
  • tests/baselines/reference/* — accepted baseline updates (categorized above);
    no .js emit baselines changed.

Function.prototype.apply accepts any array-like as its second argument per
the ECMAScript spec (CreateListFromArrayLike), so cases like
String.fromCharCode.apply(null, uint8Array) and console.log.apply(null, arguments)
work at runtime but were rejected under strictBindCallApply.

Add an array-like apply overload to CallableFunction that routes real
arrays/tuples back to the arity-checked tuple overload (Args extends readonly
any[] ? A : Args), so strictBindCallApply's arity and element-type checks are
fully preserved while non-array array-likes (arguments, typed arrays, DOM
collections) are now accepted.

Adds conformance fixture applyArrayLike.ts. Full test battery: 106377 passing,
0 failing. No JS emit baselines changed.

Fixes microsoft#61835
Copilot AI review requested due to automatic review settings July 17, 2026 15:02
@github-project-automation github-project-automation Bot moved this to Not started in PR Backlog Jul 17, 2026
@typescript-automation typescript-automation Bot added the For Backlog Bug PRs that fix a backlog bug label Jul 17, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the CallableFunction.apply typing in lib.es5.d.ts to accept non-array array-like objects (e.g. arguments, typed arrays, DOM collections) as the args parameter under strictBindCallApply, aligning the lib definition with ECMAScript’s CreateListFromArrayLike behavior and fixing #61835.

Changes:

  • Add an additional CallableFunction.apply overload that accepts ArrayLike inputs without regressing tuple/array arity checking.
  • Add a new conformance test covering accepted array-likes and guarding against strictBindCallApply arity/type regressions.
  • Accept baseline updates reflecting the new overload in type/symbol output and the expected diagnostic shape changes.

Reviewed changes

Copilot reviewed 52 out of 53 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/lib/es5.d.ts Adds an apply overload to accept non-array array-like arguments under CallableFunction.
tests/cases/conformance/functions/applyArrayLike.ts New conformance coverage for array-like apply usage and regression guards.
tests/baselines/reference/tsxReactEmitSpreadAttribute(target=es2018).types Baseline update reflecting signature/printing changes.
tests/baselines/reference/truthinessCallExpressionCoercion2.types Baseline update reflecting added overload in type display.
tests/baselines/reference/truthinessCallExpressionCoercion2.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/strictBindCallApply1.types Baseline update reflecting added overload in type display.
tests/baselines/reference/strictBindCallApply1.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/strictBindCallApply1.errors.txt Baseline update reflecting TS2769 “no overload matches” shape due to added overload.
tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.types Baseline update reflecting added overload in type display.
tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/noParameterReassignmentJSIIFE.types Baseline update reflecting added overload in type display.
tests/baselines/reference/noParameterReassignmentJSIIFE.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/noParameterReassignmentJSIIFE.errors.txt Baseline deletion because arguments is now accepted as array-like for .apply.
tests/baselines/reference/noParameterReassignmentIIFEAnnotated.types Baseline update reflecting added overload in type display.
tests/baselines/reference/noParameterReassignmentIIFEAnnotated.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/noParameterReassignmentIIFEAnnotated.errors.txt Baseline update reflecting removal of the previous .apply(arguments) error.
tests/baselines/reference/functionType.types Baseline update reflecting added overload in type display.
tests/baselines/reference/functionType.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/esDecorators-contextualTypes.2.types Baseline update reflecting added overload in type display.
tests/baselines/reference/esDecorators-contextualTypes.2.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/emitSkipsThisWithRestParameter.types Baseline update reflecting added overload in type display.
tests/baselines/reference/emitSkipsThisWithRestParameter.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/emitSkipsThisWithRestParameter.errors.txt Baseline update reflecting TS2769 diagnostic shape due to added overload.
tests/baselines/reference/declarationEmitPromise.types Baseline update reflecting added overload in type display.
tests/baselines/reference/declarationEmitPromise.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/completionsCommitCharactersAfterDot.baseline Baseline update reflecting overload count displayed in completion details.
tests/baselines/reference/coAndContraVariantInferences6.types Baseline update reflecting added overload in type display.
tests/baselines/reference/coAndContraVariantInferences6.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5(target=es5).types Baseline update reflecting added overload in type display.
tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5(target=es5).symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5(target=es5).errors.txt Baseline update reflecting TS2769 diagnostic shape due to added overload.
tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5(target=es2015).types Baseline update reflecting added overload in type display.
tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5(target=es2015).symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/asyncFunctionDeclarationCapturesArguments_es5(target=es2015).errors.txt Baseline update reflecting TS2769 diagnostic shape due to added overload.
tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.types Baseline update reflecting added overload in type display.
tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.errors.txt Baseline update reflecting TS2769 diagnostic shape due to added overload.
tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5(target=es5).types Baseline update reflecting added overload in type display.
tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5(target=es5).symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5(target=es5).errors.txt Baseline update reflecting TS2769 diagnostic shape due to added overload.
tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5(target=es2015).types Baseline update reflecting added overload in type display.
tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5(target=es2015).symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/asyncArrowFunctionCapturesArguments_es5(target=es2015).errors.txt Baseline update reflecting TS2769 diagnostic shape due to added overload.
tests/baselines/reference/asyncArrowFunctionCapturesArguments_es2017.types Baseline update reflecting added overload in type display.
tests/baselines/reference/asyncArrowFunctionCapturesArguments_es2017.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/asyncArrowFunctionCapturesArguments_es2017.errors.txt Baseline update reflecting TS2769 diagnostic shape due to added overload.
tests/baselines/reference/argumentsReferenceInFunction1_Js.types Baseline update reflecting added overload in type display.
tests/baselines/reference/argumentsReferenceInFunction1_Js.symbols Baseline update reflecting added overload symbol declaration count.
tests/baselines/reference/argumentsReferenceInFunction1_Js.errors.txt Baseline update reflecting removal of the previous .apply(arguments) error.
tests/baselines/reference/applyArrayLike.types New baseline for the added conformance test.
tests/baselines/reference/applyArrayLike.symbols New baseline for the added conformance test.
tests/baselines/reference/applyArrayLike.js New emit baseline for the added conformance test.
tests/baselines/reference/applyArrayLike.errors.txt New error baseline for the added conformance test’s intentional negative cases.

@RyanCavanaugh

Copy link
Copy Markdown
Member

Undisclosed AI

@github-project-automation github-project-automation Bot moved this from Not started to Done in PR Backlog Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

For Backlog Bug PRs that fix a backlog bug

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

The second parameter type of apply should be ArrayLike<T> instead of T[]

3 participants