Reputation: 333
The question is pretty simple, why in this situation type s
is a union of both variables.
type s = any extends boolean ? 'Yes' : 'no';
It seems logical that any type can literally be anything but is there a better explanation of this behaviour?
Upvotes: 1
Views: 84
Reputation: 328272
I could give my opinion for why this is the case, but that's not really what you're asking for, I gather.
The only canonical explanation for why this behavior happens that I can find is from the comment in lines #13287 through #13290 of checker.ts
where it's implemented (you can't directly view files that large on GitHub 🤷♂️):
// Return union of trueType and falseType for 'any' since it matches anything
if (checkType.flags & TypeFlags.Any) {
(extraTypes || (extraTypes = [])).push(
instantiateTypeWithoutDepthIncrease(root.trueType, combinedMapper || mapper)
);
}
All other references I can find to this behavior just confirm that it is that way, not why. For example, microsoft/TypeScript#27418 asks what conditional types where the checked type is unknown
should evaluate to, and mentions: "to add to the confusion, any
also has its own wildcard behavior that matches both branches". In this case, unknown extends X ? T : F
will only return T
if X
is unknown
, and F
otherwise; it never returns T | F
. 🤔
So the closest to an authoritative answer I can see here is because the implementer said "any
matches anything, so return the union of both branches". Oh well, hope that helps; good luck!
Upvotes: 2