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
Type inference of generics is order-dependent #6627
n: number as desired but m: {}. It looks like, during the second pass of type parameter inference for apply, the call signature is inferred from dit's argument before it is inferred from arg. Since f is itself generic, the default is {}. Anders Hejlsberg (@ahejlsberg), is this intended behaviour? It seems like a bug to me.
Also I am not sure why getSingleCallSignature special-cases single-call-signature-only objects. You get yet a different result if you have an extra property on f:
Now bothn: any and m: any because getSingleCallSignature doesn't return a signature, so instantiateTypeWithSingleGenericCallSignature doesn't do its instantiation at all.
When the type of an argument has a generic call signature, there are two ways we could infer from the argument:
A. Instantiate it in the context of the corresponding parameter type and infer from the resulting type, or
B. Ignore the generic call signature and infer from the other properties of the object.
If the object has a single generic call signature and no other members there's no doubt we're dealing with a generic function and we use method A. Otherwise, it's not clear what we're dealing with, so we use method B (i.e. normal inference).
When we're using method A we may be forced to fix inferences we've already made for some type parameters as described in section 4.15.2. That's what you're seeing here.
Specifically, in the call pipe(12, f) we first infer number for T from the first argument and then the second argument causes that inference to be fixed an applied using method A. But in the call to apply(f, 12) we haven't made any inferences for T by the time we fix it, so we get {}. Ideally we want to back off in the second example and handle the function argument in a second pass, but we can't tell from the shape of the argument that this is the case. We only postpone type inference for arguments that syntactically indicate they need it (this is the purpose of the isContextSensitive function in the checker).
So, long story short, this is the expected behavior given our current design.
Activity
sandersn commentedon Jan 26, 2016
A normally specified function produces the same result:
DanielRosenwasser commentedon Jan 26, 2016
What is
uin the above example?sandersn commentedon Jan 26, 2016
A typo, should be
apply(g, 12)ahejlsberg commentedon Jan 27, 2016
When the type of an argument has a generic call signature, there are two ways we could infer from the argument:
A. Instantiate it in the context of the corresponding parameter type and infer from the resulting type, or
B. Ignore the generic call signature and infer from the other properties of the object.
If the object has a single generic call signature and no other members there's no doubt we're dealing with a generic function and we use method A. Otherwise, it's not clear what we're dealing with, so we use method B (i.e. normal inference).
When we're using method A we may be forced to fix inferences we've already made for some type parameters as described in section 4.15.2. That's what you're seeing here.
Specifically, in the call
pipe(12, f)we first infernumberforTfrom the first argument and then the second argument causes that inference to be fixed an applied using method A. But in the call toapply(f, 12)we haven't made any inferences forTby the time we fix it, so we get{}. Ideally we want to back off in the second example and handle the function argument in a second pass, but we can't tell from the shape of the argument that this is the case. We only postpone type inference for arguments that syntactically indicate they need it (this is the purpose of theisContextSensitivefunction in the checker).So, long story short, this is the expected behavior given our current design.
sandersn commentedon Jan 27, 2016
Ah, so if we wrap f in a lambda, we get the right answer: