T extends U ? X : Y Conditional Types
Last updated: 2026-10-22
T extends U ? X : Y Conditional Types
Conditional types let types take an exam: T extends U ? X : Y — pick X if the condition holds, Y otherwise. It moves the runtime ternary to the type level, and combined with generics yields return types that adapt to their input.
| Group | Generics |
|---|---|
| Kind | Syntax |
| Strict mode | Not required |
ℹ️ Info The editor transpiles TypeScript to JavaScript and runs it (no type checking); see each example's Output for type-check results.
📝 Syntax
type Wrapped<T> = T extends string
? { kind: "str"; value: T }
: { kind: "num"; value: number };
type A = Wrapped<string>; // { kind: "str"; value: string }
type B = Wrapped<number>; // { kind: "num"; value: number }
// Unions distribute across the check (a distributive conditional)
type ToArray<T> = T extends unknown ? T[] : never;
⚙️ Parameters
| T extends U | The condition: if structurally compatible, take the true branch |
|---|---|
| ? X : Y | The two branches: full type expressions, may nest further conditionals |
Returns:Conditional types are pure type-level computation with no runtime code; the result depends on whether the generic argument satisfies extends.
▶ Example
Edit the code below and click Try it to see the transpiled result:
Output:
{"kind":"str","value":"hi"}
{"kind":"num","value":7}
(Runtime output after transpilation; wrap(true) is a compile error — no overload accepts boolean)
💡 Notes
ℹ️ Info A naked type parameter distributes over unions: ToArray<string | number> is string[] | number[], not (string | number)[] — the distributive conditional, also how Exclude is implemented.
💡 Tip never is the "filter out" signal: type NonNull<T> = T extends null | undefined ? never : T drops null/undefined members after distribution.
⚠️ Note Readability collapses beyond three levels of nesting: prefer mapped types or indexed access where possible, and break deep nesting into intermediate type aliases.
🏷️ Related Generics
💡 Related cases
More cases coming soon.
📚 Related tutorials
❓ FAQ
Q Conditional types or overloads?
A One or two simple branches → a single signature with a conditional type; many branches or literal-precision needs → overloads. They mix well (as the example shows).
Q Why does T extends string "hold" for string | number too?
A Distribution is at work: the union is split, checked member by member, then merged. To test the union as a whole, wrap in tuples: [T] extends [string].
Q Can conditional types be used on parameters?
A Yes but carefully: conditionals in parameter positions make caller inference subtle; the common pattern is generic parameters with a conditional return type.