TYPESCRIPT / CHAPTER 13
Conditional types and union distribution
AdvancedReason about type transformations without confusing them with runtime branches.
By the end of this chapter
- Read extends tests in conditional types
- Predict distribution over unions
- Use infer to extract relationships
The idea
A conditional type selects a type based on assignability, using T extends U ? X : Y. This is a compile-time transformation; it does not inspect runtime objects or generate a JavaScript if statement. infer can name part of a matched type, such as an array element type, so the output stays related to the input.
When the checked side is a naked type parameter, conditional types distribute over union members. That makes filters possible: a member mapped to never disappears from the resulting union. Wrapping both compared sides in tuples disables this per-member distribution and asks about the union as a whole. Work through each member separately before using a conditional type in a public API; concise syntax can hide an unexpectedly broad or empty result.
type ElementOf<T> = T extends readonly (infer U)[] ? U : T;
type KeepText<T> = T extends string ? T : never;
const value: ElementOf<number[]> = 4;
const label: KeepText<"open" | 7 | "closed"> = "open";
console.log(value, label);4 open
ElementOf extracts number; the distributive filter retains only the two string literal members.
Try it yourself
Define a conditional type that extracts a promise’s result while leaving non-promises unchanged, then test union inputs.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING