Suggestion
π Search Terms
contextually context-sensitive generic inference unused parameter method object literal
β
Viability Checklist
My suggestion meets these guidelines:
β Suggestion
When generic inference is gathering candidates, context-sensitive expressions should still be considered if it's possible to do so without observing a type parameter from the call.
π Motivating Example
declare function callIt<T>(obj: {
produce: (n: number) => T,
consume: (x: T) => void
}): void;
// Works
callIt({
produce: () => 0,
consume: n => n.toFixed()
});
// Fails for no obvious reason
callIt({
produce: _a => 0,
consume: n => n.toFixed()
});
// Fails for no obvious reason
callIt({
produce() {
return 0;
},
consume: n => n.toFixed()
});
π» Use Cases
Background: expressions can be "context-sensitive" for the purposes of inference -- this is a syntactic property of an expression that tells us whether or not an expression's type could be dependent on the inference of its contextual type. For _a => 0, this is true because the return expression might depend on _a (including in indirect ways). For produce() {, it's context-sensitive because (unlike an arrow function) it takes its parent object type for this, so could depend on the type parameter via a reference of this.
When it turns out that the type of the expression is not actually dependent on the inference of the type parameter (which would represent a true circularity, thus more understandably non-working), then this just looks busted for no obvious reason. This is a continuous source of surprise and annoyance. (TODO: link user reports)
Discussion
There are a few implementation strategies we could try, with varying trade-offs
- Proceed to do structural inference on context-sensitive expressions but mark the type parameters symbols as "off limits" with logic to back out. This is likely impractically invasive
- Perform a more robust check to determine "true" context-sensitivity -- for example,
produce: _a => 0 should not be contextually sensitive because the relational target (n: number) => T does not use T in a covariant position. There are multiple ways we could do this
- Add an optional intermediate pass when inference collected no candidates when ignoring context-sensitive expressions where we go and collect from them anyway. This pass could safely fix parameters since they'd be going to
unknown. This entire bullet point might be wrong.
- As a stopgap, consider function expressions to not be context-sensitive if all of their return expressions can be trivially seen to not depend on earlier lines of code (e.g. are literals, literals of literals,
null, or undefined). This might fix a surprisingly large class of reports
- As a stopgap, consider an object literal method to not be context-sensitive if it doesn't reference
this. I believe we already have code for this and it would fix another large class of surprises.
Suggestion
π Search Terms
contextually context-sensitive generic inference unused parameter method object literal
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
When generic inference is gathering candidates, context-sensitive expressions should still be considered if it's possible to do so without observing a type parameter from the call.
π Motivating Example
π» Use Cases
Background: expressions can be "context-sensitive" for the purposes of inference -- this is a syntactic property of an expression that tells us whether or not an expression's type could be dependent on the inference of its contextual type. For
_a => 0, this is true because the return expression might depend on_a(including in indirect ways). Forproduce() {, it's context-sensitive because (unlike an arrow function) it takes its parent object type forthis, so could depend on the type parameter via a reference ofthis.When it turns out that the type of the expression is not actually dependent on the inference of the type parameter (which would represent a true circularity, thus more understandably non-working), then this just looks busted for no obvious reason. This is a continuous source of surprise and annoyance. (TODO: link user reports)
Discussion
There are a few implementation strategies we could try, with varying trade-offs
produce: _a => 0should not be contextually sensitive because the relational target(n: number) => Tdoes not useTin a covariant position. There are multiple ways we could do thisunknown. This entire bullet point might be wrong.null, orundefined). This might fix a surprisingly large class of reportsthis. I believe we already have code for this and it would fix another large class of surprises.