C extends A but C does not extend A | B
🔎 Search Terms
union extends
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about unions and extends
⏯ Playground Link
https://www.typescriptlang.org/play/?ts=5.5.2#code/C4TwDgpgBAglC8UDeUCGAuKBGANFARpgM7ABOAlgHYDmAvlAD7JqYBMUehUJFNtA3AFgAUKEhQAQgmYYorPAGNiZKtSgCRY6AGFpKWVkZzOy3mo3DN4aAHUA9qQDWRADwAVKBAAewCJQAmRLDS2gB80m5CotZQACJ2EEQAcnbA9k7unj5+gcFMUohhEfxAA
💻 Code
type A = { a: 1, b: string} | { a: 2 , b: string};
type B = { a: 2, c: string };
type C = { a: 1 | 2, b: string };
type Works<T extends A = C> = T;
type DoesNotWork<T extends A | B = C> = T;
🙁 Actual behavior
An error tells that C does not extend A | B
🙂 Expected behavior
No error since C extends A and therefore extends A | B
Additional information about the issue
No response
This is a fallout of an extra attempt to match combinations in typeRelatedToDiscriminatedType. The normal union-based match fails here in both cases and it's just that fallback match that even allows Works to work.
I'd probably call it a design limitation as that fallback match is something that, IIRC, breaks some general rules. { prop: A } | { prop: B } isn't always interchangeable with { prop: A | B }. This fallback match also only works to a certain number of combinations so it's already not something that works universally.
Maybe the fallback match could be improved a bit. The repro is very simple and should be handle correctly IMHO.
Possibly related? https://github.com/microsoft/TypeScript/issues/36969