Contextual typing is wrong in nested function calls.
Closed this issue ยท 3 comments
๐ Search Terms
I have run into the following issue while working on a schema lib.
https://tsplay.dev/w1eekw
The type of varaible d is any for some reason, at line 78.
On the discord it was suggested that this is a compiler bug.
https://discord.com/channels/508357248330760243/1428318052205854720/1432271574689517660
๐ Version & Regression Information
- This is the behavior in every version I tried: 5.9.3, 5.8.3, 5.7.3
โฏ Playground Link
๐ป Code
// Your code here๐ Actual behavior
The type of the d param in the lambda is any.
๐ Expected behavior
It should be of type User
Additional information about the issue
No response
Please reduce this to something minimal
The repro ain't that bad if we just drop the irrelevant runtime code: TS playground
It is a design limitation. It boils down to what is described in this comment:
// When a call to a generic function is an argument to an outer call to a generic function for which
// inference is in process, we have a choice to make. If the inner call relies on inferences made from
// its contextual type to its return type, deferring the inner call processing allows the best possible
// contextual type to accumulate. But if the outer call relies on inferences made from the return type of
// the inner call, the inner call should be processed early. There's no sure way to know which choice is
// right (only a full unification algorithm can determine that), so we resort to the following heuristic:
// If no type arguments are specified in the inner call and at least one call signature is generic and
// returns a function type, we choose to defer processing. This narrowly permits function composition
// operators to flow inferences through return types, but otherwise processes calls right away. We
// use the resolvingSignature singleton to indicate that we deferred processing. This result will be
// propagated out and eventually turned into silentNeverType (a type that is assignable to anything and
// from which we never make inferences).
if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) {
skippedGenericFunction(node, checkMode);
return resolvingSignature;
}We can somewhat easily verify this is relevant because the issue gets "fixed" if we add a dummy signature to MTypeBase (TS playground):
interface MTypeBase<TSource, TValue> {
id: string;
getter: Getter<TSource, TValue>;
+(...args: never): unknown
}This makes the code defer resolving this inner call (as described in the comment)
This issue has been marked as "Design Limitation" and has seen no recent activity. It has been automatically closed for house-keeping purposes.