function broken<T>(value: T) {
type Test = keyof T extends keyof T ? 1 : 0
}
Why can't Test
in the example above be eagerly resolved to 1
? There's something I don't understand about the compiler that should answer this question for me.
Interestingly enough, there is a workaround:
function workaround<T>(value: T) {
type Test = [keyof T] extends [keyof T] ? 1 : 0
}
Playground here
The answer to the question probably involves a bug fix introduced in TypeScript 3.3. The description of the new way of evaluating conditional types is:
For a conditional type
T extends U ? X : Y
, the algorithm we use to determine whether to defer resolution of a conditional type is:
- we resolve to
Y
whenT
is not assignable toU
considering all type parameters referenced inT
andU
related (i.e.T
is definitely not assignable toU
),- otherwise we resolve to
X
whenT
is assignable toU
considering all type parameters referenced inT
andU
unrelated (i.e.T
is definitely assignable toU
),- otherwise we defer resolution.
So it looks like keyof T extends keyof T ? 1 : 0
is deferred, because keyof T1
is not assignable to keyof T2
when T1
and T2
are unrelated types. This deferral isn't exactly wrong, but it does seem like a limitation.
Indeed if I try your code in TS 3.2.1 it is eagerly resolved, so this was a change introduced for TS3.3.
Curiously my reading of that bug fix's algorithm description looks like it should apply to your workaround also. I'm not sure why [keyof T] extends [keyof T]
would change things, since [keyof T1]
isn't definitely assignable to [keyof T2]
, if T1
and T2
are unrelated. So some mystery still remains here. Haven't been able to crack it yet, so I'll probably just give up now. Oh well!
It also looks like someone reported this exact issue where X extends X ? 1 : 0
is not eagerly resolved (and they also noticed that wrapping in a one-tuple "fixes" it), and the issue was tagged as a bug, so maybe it will be addressed?
Okay, hope that helps; good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With