LLearnCode
Academy/typescript/Programming the type system

advanced · 25 minute study

Conditional types are type-level decisions

Read utility types intelligently and know when distributive behavior creates a surprising union.

Loading progressEvidence grows with practice
Useful preparation · 1 prerequisite

Use this as a map, not a lock. If these ideas are familiar, continue.

First, build a mental model

A conditional type chooses an output based on assignability. When the checked side is a naked type parameter, a union is often processed one member at a time.

  1. T extends U is a type compatibility question, not a runtime instanceof test.
  2. A naked T distributes over union members.
  3. Wrapping both sides in tuples asks about the union as a whole.
  4. infer introduces a type variable in a matching position; never can remove a union member.
Read the codetypescript · educational example
type AsArray<T> = T extends unknown ? T[] : never;
type WholeArray<T> = [T] extends [unknown] ? T[] : never;
type A = AsArray<string | number>;
type B = WholeArray<string | number>;
type ElementOf<T> = T extends readonly (infer E)[] ? E : never;
type Player = { id: string };
type P = ElementOf<readonly Player[]>;
  1. Distribute

    AsArray applies separately to string and number.

  2. Whole union

    WholeArray keeps string | number together.

  3. Infer

    ElementOf binds E to the array's element type.

Production thinking

Take this beyond the example.

Use library utility types where they already express the contract. Keep recursive types bounded and watch compiler performance on large unions.

Sources and further reading

Your evidence

unseen is a local learning signal, not a credential or proof of production competence.

Explain the mental model, then explicitly acknowledge it. Opening a page is not evidence.

Supported retries can complete this lesson. Independent evidence and delayed review determine the skill stage.

Next lesson · Keep useful literals without making false assertions →