As mentioned by @TitianCernicovaDragomir, the issue at hand revolves around conditional types with a bare type parameter T
in T extends XXX ? YYY : ZZZ
distributing over a union within T
. Although this behavior is by design, there exists a commonly used workaround: encapsulating both T
and XXX
into a one-tuple like so - [T] extends [XXX] ? YYY : ZZZ
. This adjustment removes the dependency on a bare type parameter and prevents the breakage of the union. It's likely to remain operational and supported since it comes endorsed by @ahejlsberg, the primary mind behind conditional types in TypeScript as per this source.
In your specific scenario, you could implement it as follows:
type Container<T> = [T] extends [any[]] ? ArrayContainer<T> : ObjectContainer<T>
This will interpret Container<string | number>
as
ObjectContainer<string | number>
, aligning with your desired outcome.
However, please note that
Container<string | number[]>
will be interpreted as
ObjectContainer<string | number[]>
, given that
string | number[]
isn't inherently an array. Is this acceptable? Should it be
ObjectContainer<string> | ArrayContainer<number[]>
? Or perhaps
ObjectContainer<string> & ArrayContainer<number[]>
? The ideal approach remains uncertain.
Hopefully, this provided clarity and best of luck navigating through it.