-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve inference in the presence of context-sensitive expressions #47599
Comments
Fix now available in #48538. |
Not all these cases work yet, so reopening |
Might be related to my issue: #49951, which still happens in 4.7/4.8 |
2023-10-13.15.09.40.mov |
I reckon this causes this playground's issue, too? π€ |
I noticed that these issues always contain anonymous functions. I am getting the same issue using simple generic types. You can see it in this playground. |
I've managed to conjure another example of this: https://tsplay.dev/mxpM7m Referencing my SO issue and subsequent discussion for completeness. |
The inference source for The intermediate argument's type ( The problem is that the first pass will always use constraints as the fallback for the inferred types. Since - at that point in time - no candidate for Do you even need You can work around this if you make an inference for interface Base {
x: string;
}
interface Foo extends Base {
y: number;
}
type Fn<T> = (t: T) => void;
declare const FooFn: Fn<Foo>;
declare const FooBase: Fn<Base>;
declare const FooExtra: Fn<Foo & { extra: string }>;
type Baz = <R extends Base, F extends Fn<R>>(arg: {
x: (bar: Foo) => R;
y?: (F & Fn<R>)[];
}) => R;
declare const baz: Baz;
const R1 = baz({ x: (ctx) => ctx });
const R2 = baz({ x: (ctx) => ctx, y: [FooFn] });
const R3 = baz({ x: (ctx) => ctx, y: [FooBase] });
const R$ = baz({ x: (ctx) => ctx, y: [FooExtra] }); // error (as expected, although the location of the error could be better) |
Yeah, in a real world scenario, the type(s) of The use of an intersection type's a great trick! Very handy to know... One limitation, though, if I actually alter the return type of Here's an example where the return type is a union: https://tsplay.dev/N97gMW I wonder if |
Yeah, I don't have an answer to that π An interesting experiment to run would be not ignoring the inferences that could be made from this |
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 => 0
should not be contextually sensitive because the relational target(n: number) => T
does not useT
in 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.The text was updated successfully, but these errors were encountered: