TypeScript: Compiler incorrectly reports parameter/call target signature mismatch when using the spread operator
The compiler incorrectly reports a parameter/call target signature mismatch when using the spread operator. Pasting this code into the TypeScript Playground:
function foo(x: number, y: number, z: number) { }
var args = [0, 1, 2];
foo(...args);
produces this error:
Supplied parameters do not match any signature of call target.
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 176
- Comments: 57 (12 by maintainers)
Commits related to this issue
- Define Schema and add workaround for Microsoft/TypeScript#4130 — committed to MichalZalecki/policeman by MichalZalecki 8 years ago
- Breaking change !!! Most cloud services offer database connection string as URI, not username and password. This branch adds ability to initialize Sequelize using URI connection string, eg. "postgres:... — committed to kukoo1/sequelize-typescript by deleted user 7 years ago
this is currently by design. but we should reconsider it.
@jpike88 I know you mean well, but you might not realize statements like these are counter productive. The issue is on their TODO for milestones 2.7 or 2.8 it looks like. It might seem like an obvious thing to fix, but when you have thousands of obvious things to fix you can’t possibly fix them all at the same time, and continue to improve other things that are expected of them. The best way to voice your vote is to give the original post at the top a 👍 reaction. This is free software after all and they don’t owe us anything. That said, that’s just my take, another user of TS like you 🕺
How is this still an issue? Spread operators are a perfectly compliant way to work in JS, so TS should account for it properly.
I’m currently having this issue implementing styled-component’s media templates example.
My workaround is to use
css.call, which at least works with theany[]-typed args:We have recently made a change to allow spreading into call expressions if the target is all optional (see https://github.com/Microsoft/TypeScript/pull/15849). The change works by treating a spread output as an infinite set of optional arguments.
With this change, here is the current state in examples:
In the last example, the compiler has no way to validate that
argssatisfy the requiredbaz, since the length ofargscan not be statically validated.What is left in this area is to allow tuples with known size to satisfy functions with required arguments of the same length… but this is not as simple as it may sound. e.g.:
Cast to spread value as the
ParameterTypeof the function you are passing arguments to.Another example
TS2346: Supplied parameters do not match any signature of call target.
Even if I check the length, I still get this error:
Edit:
To clear up confusion, I was redirected from here, which states:
That issue was considered a duplicate of this issue.
@ahejlsberg this issue either persists or there is a regression in the latest TS version. The comment above (https://github.com/microsoft/TypeScript/issues/4130#issuecomment-691115905) demonstrates it perfectly.
@owlcode this is in TS 2.4 but the playground is on TS 2.3 until after 2.4 releases.
Here is a reduced form of @Haaxor1689’s example: Playground link
@mateja176 This also seems to work and might better suit some use cases.
or
👍 Having the same issue, with the specific use case of the
Dateconstructor:I feel like this is still a problem (just encountered this). Is there another open issue for this, or would it be relevant to re-open this one?
I was actually hit with this issue when I renamed a
.jsfile to.ts. Anyhow, one example of “not all valid JS is valid TS”.@tjoskar change your code to
(playground) And the error’s back.
Surprisingly, if you were to change the last line to
foo(3, ...args);- there will be no error.@darekf77, or if you say that
argsis a tuple:ts-playground
@kitsonk can you open a separate bug for that? It would be easier to consider in isolation, and is probably a small tweak to the existing rules, rather than a complex change.
And the same is for when
argsis ofany-typeI feel like this still isn’t working. Here is my example
It shouldn’t really matter what is the type of
props.onSetValue, because I just take the parameters type and pass it to the function which I got the the type from and it still gives theExpected 2 arguments, but got 0 or more.error.Playground link
@smashdevcode For me solution was to add @ts-ignore
example here: https://stackblitz.com/edit/typescript-ecymei?embed=1&file=index.ts
I opened a PR for this at #18004.
This does appear to be fixed in TS 2.4,
However, there appears to be a new bug in TS 2.4:
Happens when you try to spread an iterable (
[...obj]).And yet a different bug (I think) in
2.4.1-insiders.20170615which I haven’t been able to figure out yet.I don’t know how to get around this one either. Casting our arrays to
any[]won’t help.Nevermind, we can fix the definition of
Console,And then cast the
consoleobject:That’ll have to do for now.
@smashdevcode, @tjoskar, I’m looking for some real-world uses of this feature. Specifically, do you expect to spread arrays or tuples (or both maybe)? Here are couple of toy examples:
Now any of
a1,a2,a3can be applied to the first two functions, and any oft1,t2can be applied to the second two.Notice that with arrays:
any.)With tuples:
(number | string)[]not[number, number, string]). In toy code this erases any savings in brevity, but it might be OK in a real project that already defines lots of interfaces.