After delving deep into the source codes for an entire day, I believe I have finally uncovered the solution:
Essentially, <T>
was deduced as 'a'
and 'b'
from T
and [T]
respectively, which were identified as candidate types. These two candidate types possess varying priorities: T
within the union type definition has a unique priority value of 1
(Refer to https://github.com/Microsoft/TypeScript/blob/master/src/compiler/types.ts, line 4398, the NakedTypeVariable
enum value), while [T]
has a standard priority value of 0
, indicating higher priority in ordering.
Subsequently, the higher priority value of 0
will supersede 1
immediately, prior to scrutinizing the type specifics. This is why the type 'a'
was replaced. In instances where they share the same priority value, they would be merged (as shown below).
The most straightforward solution is to eliminate <T extends 'a' | 'b'>
. Without any form of assertion, T
within [T]
will be inferred as a broader type string
following the decomposition of a virtual expression ['b']
.
I also discovered the compiler's handling of scenarios where multiple candidate types are present: If candidate types share a fundamental (e.g., string, number) covariant type, they are combined using the union symbol |
. Alternatively, the compiler selects the leftmost type for which no subsequent types are super types.