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
Infer operator returning container type instead of applied genericΒ #48772
I expected ExtractedAdditionalContext to be AdditionalContext or { customValue: string }, and for test1 to compile without error.
π Expected behavior
ExtractedAdditionalContext is AdditionalContext & BaseContext<Config> which is the same type as Context. test1 results in a compiler error of:
Type 'AdditionalContext' is not assignable to type 'AdditionalContext & BaseContext<Config>'.
Type 'AdditionalContext' is missing the following properties from type 'BaseContext<Config>': foo, config
Additional notes
When I remove the config property from BaseContext the issue is resolved.
If you keep substituting in the expansions of each type and see the operation being performed, this is a correct inference -- as in many cases, there are multiple equally correct inferences that can be made, and as a result of the linked PR we switched from a certain correct inference to a different correct inference. In general it's not safe to assume that inferring onto a T & U will reliably "break apart" a source type which was also constructed through a T & U - this can happen, but is not guaranteed to.
Thanks for the quick reply! I can appreciate how this is a correct inference, but it's certainly surprising. I'm sure a case exists, but I'm having a hard time imaging a time where I'd want the current result.
I guess it's partially surprising because I wrote FullContext<any, infer TAdditionalContext>, not infer TContext & BaseContext<any>. The syntax suggests that I'm asking the compiler to tell me what was provided to the second generic of the type. Clearly that's not how the infer keyword works, but that begs the question -- can we have that feature? :)
The syntax suggests that I'm asking the compiler to tell me what was provided to the second generic of the type.
Yeah, inference is structural, not nominal, so the type system is always working backwards from the output of the generic to figure out what should go in the infer position. It's a bit like solving for x in f(x, y) = z given fixed y and z - the solution isn't guaranteed to be unique, depending on what f does with its arguments.
Clearly that's not how the infer keyword works, but that begs the question -- can we have that feature? :)
I'm not a TypeScript team member, but from what I do know about how the type system works I'm going to say probably not - in many cases the compiler doesn't even know which type alias a type came from, so infer always has to be done structurally.
Nothing's impossible but in general we're not keen to spend time tweaking things in the grey areas of inference - there are always going to be cases where there's a structural inference going on here, so making 6 out of 10 cases work as opposed to 4 out of 10 cases doesn't really change the situation much.
Yeah, inference is structural, not nominal, so the type system is always working backwards from the output of the generic to figure out what should go in the infer position. It's a bit like solving for x in f(x, y) = z given fixed y and z - the solution isn't guaranteed to be unique, depending on what f does with its arguments.
Thanks, I was missing this context and it explains why this is so difficult.
Nothing's impossible but in general we're not keen to spend time tweaking things in the grey areas of inference
That's reasonable and I understand why the team takes that position. I'll close this issue, thanks for you time.
Dave Campion (@dpchamps) came up with a good solution to my problem that I'll post here for others. Instead of inferring the generic, we can omit the keys in BaseContext from FullContext. This can omit too much if AdditionalContext contains keys that are also in BaseContext, but that's not a problem in my case. Here's a working example.
Activity
RyanCavanaugh commentedon Apr 19, 2022
Bisected to #42284
RyanCavanaugh commentedon Apr 19, 2022
If you keep substituting in the expansions of each type and see the operation being performed, this is a correct inference -- as in many cases, there are multiple equally correct inferences that can be made, and as a result of the linked PR we switched from a certain correct inference to a different correct inference. In general it's not safe to assume that inferring onto a
T & Uwill reliably "break apart" a source type which was also constructed through aT & U- this can happen, but is not guaranteed to.kschat commentedon Apr 19, 2022
Thanks for the quick reply! I can appreciate how this is a correct inference, but it's certainly surprising. I'm sure a case exists, but I'm having a hard time imaging a time where I'd want the current result.
I guess it's partially surprising because I wrote
FullContext<any, infer TAdditionalContext>, notinfer TContext & BaseContext<any>. The syntax suggests that I'm asking the compiler to tell me what was provided to the second generic of the type. Clearly that's not how theinferkeyword works, but that begs the question -- can we have that feature? :)fatcerberus commentedon Apr 20, 2022
Yeah, inference is structural, not nominal, so the type system is always working backwards from the output of the generic to figure out what should go in the
inferposition. It's a bit like solving forxinf(x, y) = zgiven fixedyandz- the solution isn't guaranteed to be unique, depending on whatfdoes with its arguments.I'm not a TypeScript team member, but from what I do know about how the type system works I'm going to say probably not - in many cases the compiler doesn't even know which type alias a type came from, so
inferalways has to be done structurally.RyanCavanaugh commentedon Apr 20, 2022
Nothing's impossible but in general we're not keen to spend time tweaking things in the grey areas of inference - there are always going to be cases where there's a structural inference going on here, so making 6 out of 10 cases work as opposed to 4 out of 10 cases doesn't really change the situation much.
kschat commentedon Apr 21, 2022
Thanks, I was missing this context and it explains why this is so difficult.
That's reasonable and I understand why the team takes that position. I'll close this issue, thanks for you time.
kschat commentedon Apr 21, 2022
Dave Campion (@dpchamps) came up with a good solution to my problem that I'll post here for others. Instead of inferring the generic, we can omit the keys in
BaseContextfromFullContext. This can omit too much ifAdditionalContextcontains keys that are also inBaseContext, but that's not a problem in my case. Here's a working example.