Description
Not sure if this is a duplicate, I've searched, but couldn't find anything. Basically, allow union types to narrow types to fit constraints. I ran into this issue today, not allowing me to properly type a variable that I could clearly write the type for.
Would also negate the need for #12424 I think.
Specific case with fallbacks:
type A<T extends string> = { a: T };
type B<T> = A<T> | { b: number }
let x: B<string> // Should infer to type '{ a: string } | { b: number }'
let y: B<number> // Should infer to type '{ b: number }'
In this sample, we know there's an option that works regardless of T, so we only include the option with T if the constraint is met.
More general version allows pattern matching:
type A<T extends string> = { a: T };
type B<T extends number> = { b: T };
type C<T extends string | number> = A<T> | B<T>
let x: C<string> // Should infer to type '{ a: string }'
If the type system were able to solve this case, we'd basically get a really simple version of doing conditionals, type matching at a type level, etc.
Edge cases:
I would not make it order dependent because union types are not ordered. If multiple parts of the union check out, they should all be included. This is not an attempt at writing function overloads in types, though it could potentially be used as such for certain cases.