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
Key that must exist on generic type T cannot be used to index type type T #51161
"Cannot be used to index", "generic conditional", "generic extends ternary branch"
Seems similar to #50462 and #50465 but both of those tickets have since been fixed in 4.8.1 and 4.9 respectively while my example is still broken in the playground using 4.8 or nightly (which as of writing this is v4.9.0-dev.20221013)
In TS versions greater than v4.6.4 (I've only tested versions available in the playground) the T['oneofKind'] on line 3 is highlighted as an error: Type '"oneofKind"' cannot be used to index type 'T'.(2536).
🙂 Expected behavior
No error on line 3 as "oneofKind" can in fact be used to index into type T since T must have property "oneofKind".
Some things to note about this. If you remove | { oneofKind: undefined } from the AnyOneof type the error goes away (but is obviously no longer the type I need). In fact, it seems like simply having the AnyOneof not be a union removes the error so perhaps this is just an issue with indexing into a union. 🤔
The other odd thing about this is that the AnyOneofKind still computes the correct results even with the error.
// should be nevertypewrongKey=AnyOneofKind<{oneofKind: 'foo',bar: 1,// wrong key}>;// should be "foo"typefoo=AnyOneofKind<{oneofKind: 'foo',foo: 1,}>;// should be "foo" | "bar"typefoobar=AnyOneofKind<{oneofKind: 'foo',foo: 1,}|{oneofKind: 'bar',bar: 1,}>;
Thanks, that certainly fixes the error. I still don't understand why since the oneofKind property could only ever have a value of type string | undefined, so I'd have assumed constraining that union to keyof T would've constrained the union to string already.
Right, but (string | undefined) & (string | symbol) is just string. So this still seems like a bug unless I'm misunderstanding how the generic constraints work.
exporttypeAnyOneofKind<TextendsAnyOneof>=Textendsunknown ? keyofT&T['oneofKind'] : T
Right, but (string | undefined) & (string | symbol) is just string
(T | U) & (T | V) is T, but (T & U) | (T & V) is correctly possibly never. I think the logic in the linked PR is correct and it's proper to defer the type computation here, otherwise it'd be possible to construct some nonsense types.
It happens in this case that the definition of AnyOneof precludes that possibility, since it's seeable in advance that "oneofKind" & string isn't never. But we (as the authors) can also use that information to choose the simpler definition above.
If someone is able to fix this without regressing other cases, that's fine, but this is Backlog milestone unless there are definitions without an available rewrite.
Activity
jcready commentedon Oct 13, 2022
Some things to note about this. If you remove
| { oneofKind: undefined }from theAnyOneoftype the error goes away (but is obviously no longer the type I need). In fact, it seems like simply having theAnyOneofnot be a union removes the error so perhaps this is just an issue with indexing into a union. 🤔The other odd thing about this is that the
AnyOneofKindstill computes the correct results even with the error.MartinJohns commentedon Oct 13, 2022
You can write:
jcready commentedon Oct 13, 2022
Thanks, that certainly fixes the error. I still don't understand why since the
oneofKindproperty could only ever have a value of typestring | undefined, so I'd have assumed constraining that union tokeyof Twould've constrained the union tostringalready.MartinJohns commentedon Oct 13, 2022
I'm not certain, but I believe the issue is that
keyof Tnow includessymbol.jcready commentedon Oct 13, 2022
Right, but
(string | undefined) & (string | symbol)is juststring. So this still seems like a bug unless I'm misunderstanding how the generic constraints work.typescript-bot commentedon Oct 13, 2022
The change between release-4.5 and main occurred at fc82c67.
RyanCavanaugh commentedon Oct 13, 2022
PR for that commit is #46812
RyanCavanaugh commentedon Oct 13, 2022
An equivalent type, as far as I can tell, is
(T | U) & (T | V)isT, but(T & U) | (T & V)is correctly possiblynever. I think the logic in the linked PR is correct and it's proper to defer the type computation here, otherwise it'd be possible to construct some nonsense types.It happens in this case that the definition of
AnyOneofprecludes that possibility, since it's seeable in advance that"oneofKind" & stringisn'tnever. But we (as the authors) can also use that information to choose the simpler definition above.If someone is able to fix this without regressing other cases, that's fine, but this is Backlog milestone unless there are definitions without an available rewrite.
RyanCavanaugh commentedon Oct 13, 2022
FYI Wesley Wigham (@weswigham) in case it turns out there's a trivial fix you can think of