Question presented to candidate:
"type ToArray<T> = T extends unknown ? T[] : never gives string[] | number[] for string | number, not (string | number)[]. Why? How do you turn that off, and how does infer behave when the input is a union?"
What a strong answer should cover:
- Distribution: when the checked type is a naked type parameter instantiated with a union, the conditional type is applied to each member separately and the results are unioned (documented since TypeScript 2.8)
- Only a bare type parameter distributes: a union written inline, or
Twrapped in{ v: T }, is checked as a whole - Turning it off with
[T] extends [U], and turning it on deliberately withT extends unknown ? ... : never - Consequences:
booleandistributes astrue | false,nevergivesnever(hence[T] extends [never]forIsNever), andExclude/Extractdepend on it inferinside a distributive conditional runs per member (Unwrap<Promise<string> | number>isstring | number); with the tuple wrapper it must match the whole union;infer X extends C(TypeScript 4.7) filters while extracting- Advanced uses:
IsUnion, and contravariantinfercandidates giving an intersection (UnionToIntersection)
Code / implementation expected: Yes β show ToArray both ways and an infer-based unwrap on a union.