You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Go to Definition assumes use of rest parameters when spread syntax is used with empty array unless of type [] #54977
functionfunc(): void;functionfunc(...args: any[]): void;functionfunc(...args: any[]): void{}func(...[]);// first declaration highlightedfunc(...([]asany[]));// second declaration highlighted
🙁 Actual behavior
An array of type other than [] is assumed to always lead to the overload with rest parameters when Go to Definition is called, despite the fact that it can be empty.
changed the title [-]Go to Definition assumes se of rest parameters when spread syntax is used with empty array unless of type `[]`[/-][+]Go to Definition assumes use of rest parameters when spread syntax is used with empty array unless of type `[]`[/+]on Jul 12, 2023
TypeScript might compute an "effective arguments list" at times when you are using spreads. You are effectively passing it 0 arguments with ...[] and that matches the first overload. An empty array is considered to be a 0-length tuple and that's not the same as any[].
It is perfectly fine that the first overload is chosen for the [] type. What I find problematic is the assumption that all arrays of type any[] are not empty. I used the empty array explicitly to illustrate the problem, but it could be any array whose contents we are not aware of, so either of the overloads could apply.
In TS only a single overload can be matched anyway (from the top to the bottom) so without even going into how TS treats array I still think this is OK.
It is not about overload matching for a particular function call with particular parameter values, it is about the Go to Definition feature which, as far as I can tell, only works with symbols and not values. Try Ctrl + clicking the second function call in the playground and you'll see the second declaration highlighted, but instead, a list with both declarations should open up.
Ye, I know what you are saying here - but the fact is that Go to Definition actually goes to the resolved signature (can also be tested using a different demo here). This behavior is actually quite helpful because you can easily jump to the matched overload - and if you need to look at others they usually are just close to it.
The spread/rest is IMO a red herring here. This is analogous to writing:
declarefunctionfoo(x: string): void;declarefunctionfoo(x: string|number): void;declareconstbar: string|number;foo(bar);// go to def picks second overload
Yes, sometimes it will match the first overload "at runtime" (ignoring the fact that overloads are pure type info and don't exist at runtime, except insofar as they are encoded in the single function implementation), just as an any[] might sometimes be [] at runtime, but the call only resolves to the string | number overload regardless. Same principle.
Activity
[-]Go to Definition assumes se of rest parameters when spread syntax is used with empty array unless of type `[]`[/-][+]Go to Definition assumes use of rest parameters when spread syntax is used with empty array unless of type `[]`[/+]Andarist commentedon Jul 12, 2023
TypeScript might compute an "effective arguments list" at times when you are using spreads. You are effectively passing it 0 arguments with
...[]and that matches the first overload. An empty array is considered to be a 0-length tuple and that's not the same asany[].I think this works as expected.
aweebit commentedon Jul 12, 2023
It is perfectly fine that the first overload is chosen for the
[]type. What I find problematic is the assumption that all arrays of typeany[]are not empty. I used the empty array explicitly to illustrate the problem, but it could be any array whose contents we are not aware of, so either of the overloads could apply.Andarist commentedon Jul 12, 2023
In TS only a single overload can be matched anyway (from the top to the bottom) so without even going into how TS treats array I still think this is OK.
aweebit commentedon Jul 12, 2023
It is not about overload matching for a particular function call with particular parameter values, it is about the Go to Definition feature which, as far as I can tell, only works with symbols and not values. Try Ctrl + clicking the second function call in the playground and you'll see the second declaration highlighted, but instead, a list with both declarations should open up.
Andarist commentedon Jul 12, 2023
Ye, I know what you are saying here - but the fact is that Go to Definition actually goes to the resolved signature (can also be tested using a different demo here). This behavior is actually quite helpful because you can easily jump to the matched overload - and if you need to look at others they usually are just close to it.
fatcerberus commentedon Jul 12, 2023
The spread/rest is IMO a red herring here. This is analogous to writing:
Yes, sometimes it will match the first overload "at runtime" (ignoring the fact that overloads are pure type info and don't exist at runtime, except insofar as they are encoded in the single function implementation), just as an
any[]might sometimes be[]at runtime, but the call only resolves to thestring | numberoverload regardless. Same principle.aweebit commentedon Jul 12, 2023
Thanks to both of you for clearing up my misconceptions!