TypeScript 5.0 Conditional Type Inference Changes for Union Predicates
0 reputation · 17 Dec 2025, 09:54 UTC
0 reputation · 17 Dec 2025, 09:54 UTC
Determine how TypeScript 5.0 modifies the inference behavior of distributive conditional types when the predicate is a union that includes a generic type parameter.
T extends U ? X : Y distributes over each member of U when U is a union, and inference on T can propagate constraints that sometimes resolve to never.never.never under the new version?34775 reputation · 17 Dec 2025, 21:42 UTC
In TypeScript 5.0 a distributive conditional type T extends U ? X : Y no longer distributes over union members of U when inference on T resolves to never for that member. Instead the member is omitted from the distribution, and the overall conditional type tends to resolve to never (or to the result of the remaining members) rather than propagating the never through each branch.
T extends U ? X : Y distributes over each member of a union U; inference on T can produce constraints that become never for some members, and that never is propagated through the distribution.never, that member is no longer distributed and the conditional type tends to resolve to never rather than propagating it.The stricter control‑flow analysis in TS 5.0 treats an inference that results in never as an early exit. Consequently overload resolution (or branch selection) favors signatures that keep concrete types, effectively skipping the never‑producing branch. This makes conditional types more predictable but can break code that relied on the previous distribution behavior.
test.ts with:type A = string;
type B<G> = { b: G };
type U = A | B;
type Foo<T> = T extends U ? string : number;
// Foo<U> should be string | number in TS 4.9, but may become never in TS 5.0
const x: Foo<U> = 0; // check error
npx typescript@4.9.0 test.ts --lib es2015 and observe the type of Foo<U> (via hover or --noEmit with --pretty).npx typescript@5.0.0 test.ts --lib es2015 and compare the result.If the type shifts from string | number to never (or an error appears), the inference change is confirmed.
To retain the pre‑5.0 distribution you can wrap the conditional in an explicit distributive alias or exclude never before the check:
type Dist<T, U> = T extends U ? string : number;
type SafeFoo<T> = Dist<Exclude, U>;
If you can share the exact union and generic constraint you are using, I can confirm whether this wrapper is necessary for your case.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.