-
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
Granular inference for generic function type arguments #20122
Comments
Duplicate of #10571? |
@mhegazy Not really. I don't want any new syntax for skipping type parameters. You should simply be able to not supply anything for unnecessary type parameters and have it work. |
They're all slightly different proposals. #10571 wants a syntax for marking type parameters as "to be inferred", #14400 wants to enforce a distinction between normal type parameters and those with defaults, and only infer the latter. This issue is about simply making existing syntax have different semantics. I don't want any new keywords or syntax (although some future additions could be made to make things clearer), I just want the syntactically valid If it helps you track things, I'm fine with you folding this issue into either one, I just wanted to clarify what I'm proposing is distinct from those proposals. |
Either I'm misunderstanding this or I strongly disagree. If you write function fn<T>(x: T) { } you should not be able to invoke it like this: fn<Dog>(someAnimal); Even though we would infer |
@RyanCavanaugh Not following you. You're already able to call I'm also not proposing that that behavior of that should change in any way that I can think of. The semantics of the change I'm proposing are identical to adding a Could you make a full snippet I can stick in playground? |
type Animal = { move(): void };
type Dog = Animal & { woof(): void };
declare function fn<T>(x: T);
const a: Animal = { move() { } };
// Correct (IMHO) error today
fn<Dog>(a); |
I'm not entirely clear why this isn't an error, but pretending function contravariance worked in TypeScript, change the above proposal to emitting a This would prevent assignability of |
Actually in the latest version that is an error, I was just using an old TypeScript. So how about something like that? Full example for you to try: type Animal = { move(): void };
type Dog = Animal & { woof(): void };
const fn = <T>(x: T, dummy?: { t?: (x: T) => {} }) => { }
const a: Animal = { move() { } };
fn(a, undefined as any as { t: (x: Dog) => {} }); Which produces:
I've confirmed that it also works as expected for the |
this will be a breaking change for defaults. which might not be a bad break, but we will need to do additional analysis on our real-world code bases and see if any popular patterns that would be affected by this. |
With #23696 you can infer |
Looking at it again, I really don't see a difference between this and #10571 that doesn't imply a massive breaking change.
|
Consider the following function, based on this StackOverflow question:
Currently it is not possible to use this function ergonomically. You must always supply both type arguments, even though
TKey
can comfortably be inferred fromprops
.It should be possible to invoke a generic function and specify a named subset of the type parameters, i.e.
pluckFuncs<TComponent = { a: () => string }>(['a'])
, and have inference decide (or fail to decide) the remaining type parameters (in this caseTKey
).In terms of the desired semantics, the inference should treat explicit type arguments no differently from the types of the function's value arguments, except for the fact that no values will be forthcoming at the invocation site.
In other words, doing this:
should behave no differently from when I just add a dummy value argument to serve as an inference site:
Aside:
The workaround one might come up with is to give
TKey
a default ofkeyof TComponent
:This seems like a sensible thing to do, but isn't really the semantics we're looking for. When you try to use it:
What's happened is that we only have one degree of freedom here. Defaulting
TKey
to a type derived fromTComponent
has ended up imposing an additional constraint onTComponent
instead of constraining the parameter that usesTKey
with respect toTComponent
.I think the behavior seen above is valid, and that default type arguments are a totally different ballgame. They shouldn't be mixed up in our problem with independent inference of type parameters when instantiating abstract function types.
The text was updated successfully, but these errors were encountered: