Skip to content

Cannot mix both fixed and rest arguments using '.call' when using '--strictBindCallApply' #37834

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
rbuckton opened this issue Apr 8, 2020 · 3 comments
Labels
Needs Investigation This issue needs a team member to investigate its status.
Milestone

Comments

@rbuckton
Copy link
Contributor

rbuckton commented Apr 8, 2020

TypeScript Version: 3.9.0-dev.20200328

Search Terms: strict call rest arguments

Code

class C {
    use<A extends any[]>(fn: (this: this, obj: this, ...args: A) => void, ...args: A) {
        fn.bind(this, this)(...args); // ok
        fn.bind(this)(this, ...args); // error
        fn.call(this, this, ...args); // error
    }
}

Expected behavior:

The 2nd and 3rd cases above should be ok

Actual behavior:

The 2nd and 3rd cases above report errors.

Playground Link: Playground

Related Issues:

@rbuckton
Copy link
Contributor Author

rbuckton commented Apr 8, 2020

The bind error case is likely a design limitation until we can represent spreading a non-array-type in a tuple type, i.e. [T, ...U] (if U has an array or tuple type as a base constraint).

We could possibly resolve the call error case by adding a few overloads.

@rbuckton
Copy link
Contributor Author

rbuckton commented Apr 8, 2020

The bind case could also be partially resolved by specifying a fixed set of unbound type arguments, i.e.:

bind<T, A0, A extends any[], R>(
  this: (this: T, arg0: A0, ...args: A) => R,
  thisArg: T
): (arg0: A0, ...args: A) => R;

This is similar to the existing bind<T, A0, A extends any[], R> overload, except that it passes on arg0 and allows us to have the fixed argument list.

@rbuckton
Copy link
Contributor Author

rbuckton commented Apr 8, 2020

Unfortunately, just adding overloads doesn't address this. I added these to call and ended up with cases that should be errors compiling successfully:

    call<T, A0, A extends any[], R>(this: (this: T, arg0: A0, ...args: A) => R, thisArg: T, arg0: A0, ...args: A): R;
    call<T, A0, A1, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, ...args: A): R;
    call<T, A0, A1, A2, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2, ...args: A): R;
    call<T, A0, A1, A2, A3, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3, ...args: A): R;

From tests\cases\conformance\functions\strictBindCallApply1.ts:

declare function foo(a: number, b: string): string;
...
let c03 = foo.call(undefined, 10, "hello", 30);  // Error

The above call reports an error without the overloads: error TS2554: Expected 3 arguments, but got 4., but with the overloads we infer a function type that has the excess argument A3 and foo is assignable to that type so we don't report an error.

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Jun 1, 2020
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Jun 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
Development

No branches or pull requests

2 participants