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
YwhenTis not assignable toUconsidering all type parameters referenced inTandUrelated (i.e.Tis definitely not assignable toU),- otherwise we resolve to
XwhenTis assignable toUconsidering all type parameters referenced inTandUunrelated (i.e.Tis 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