Syncing account progress…

Back

Advanced · 18 min

Conditional types

Select types with conditions and recognize union distribution.

Choose a type by its shape

A conditional type checks whether one type is assignable to another. Here "infer" captures an array element type; non-arrays keep their original type. This is a compile-time decision, not a runtime branch.

type ElementOf<T> = T extends readonly (infer Item)[] ? Item : T;
const first: ElementOf<string[]> = "Travel";
const second: ElementOf<number> = 4;
console.log(first + ": " + second);

Output

Travel: 4

Control union distribution

A condition on a bare type parameter distributes across union members. Wrapping both sides in tuples tests the union as a whole. Use distribution deliberately when filtering members; use the tuple form for a whole-type decision.

type OnlyText<T> = T extends string ? T : never;
type AllText<T> = [T] extends [string] ? true : false;
const word: OnlyText<string | number> = "Hi";
const all: AllText<string | number> = false;
console.log(word + ": " + all);

Output

Hi: false

Put it into practice

  1. Predict the output and explain which relationships the types enforce.
  2. Fix the task while preserving its type contract, then check both practice questions.

Try it yourself

Code runs on this device. When you are signed in, drafts sync to your account.

Use the extracted element type

Change "first" to the string "Travel" while keeping the conditional type.

Show solution
type ElementOf<T> = T extends readonly (infer Item)[] ? Item : T;
const first: ElementOf<string[]> = "Travel";
const second: ElementOf<number> = 4;
console.log(first + ": " + second);

The conditional type resolves before execution. A string value satisfies the extracted element type, while the numeric fallback remains valid.

Practice