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
In v3.3.x which I was working with (before testing against latest) c was inferred as {}, so the return type would be { height: 100 } (i.e. all other properties were dropped).
If you do the exact same code with a rest parameter instead of an array, it works absolutely fine:
This is basically a design limitation for the same reason that this wouldn't work with an explicit parameter list if the parameters were in the opposite order - given multiple context-sensitive things that need inference, we proceed in left-to-right order of parameters, including for expansion of rest tuples.
When the inference sites are all part of a single argument tuple, there's no mechanism or heuristic to do multiple rounds of inference - it's the same as if we were trying to infer to multiple properties of the same object (in fact, it's exactly that, since a tuple in a non-rest position is just an object as far as inference is concerned).
See #30134 for general discussion of an algorithm that would be able to handle this.
Is it because the function with rest params is converted to a function without rest params first?
So, (...args : [A, B, C, D]) becomes (a : A, b : B, c : C, d : D).
Then, it does inference for A, B, C, D.
And they're all considered different objects?
I can't use the rest parameter approach as my actual code looks more like this: <A, B, C>(opts: { inferredStuff: [ (a: A) => B, (b: B) => C ] }) => Wrapper<C> where this is just one of several optional properties
Jack (@jackmellis) I can't think of a workaround that doesn't have effects on how the function would be called. TS just can't do multiple rounds of inference against the same object, so the inference sites need to be split up across either multiple parameters or multiple calls
Activity
AnyhowStep commentedon Nov 1, 2019
I don't know why this happens but my personal experience aligns with yours.
TS infers more stuff, and is more accurate with inferences when it comes to tuple rest parameters.
It's not so good with "regular" tuple parameters.
It's why I tend to avoid "regular" tuple parameters nowadays.
Also, 3.6.3 TS Playground
RyanCavanaugh commentedon Nov 1, 2019
This is basically a design limitation for the same reason that this wouldn't work with an explicit parameter list if the parameters were in the opposite order - given multiple context-sensitive things that need inference, we proceed in left-to-right order of parameters, including for expansion of rest tuples.
When the inference sites are all part of a single argument tuple, there's no mechanism or heuristic to do multiple rounds of inference - it's the same as if we were trying to infer to multiple properties of the same object (in fact, it's exactly that, since a tuple in a non-rest position is just an object as far as inference is concerned).
See #30134 for general discussion of an algorithm that would be able to handle this.
AnyhowStep commentedon Nov 2, 2019
Is it because the function with rest params is converted to a function without rest params first?
So,
(...args : [A, B, C, D])becomes(a : A, b : B, c : C, d : D).Then, it does inference for
A, B, C, D.And they're all considered different objects?
jackmellis commentedon Nov 4, 2019
Ryan Cavanaugh (@RyanCavanaugh) is there any sort of workaround I can employ?
I can't use the rest parameter approach as my actual code looks more like this:
<A, B, C>(opts: { inferredStuff: [ (a: A) => B, (b: B) => C ] }) => Wrapper<C>where this is just one of several optional propertiesRyanCavanaugh commentedon Nov 4, 2019
AnyhowStep correct
Jack (@jackmellis) I can't think of a workaround that doesn't have effects on how the function would be called. TS just can't do multiple rounds of inference against the same object, so the inference sites need to be split up across either multiple parameters or multiple calls