Study notes · 10% of the exam

Conditional, Template Literal and Recursive Types

Conditional types are type-level if/else: `T extends U ? X : Y`. Combined with `infer`, distribution, template literals and recursion, they let you compute types from other types.

Key points

  1. 1

    extends in a conditional type is an assignability check. infer X binds a type variable from the match and is usable only in the true branch.

  2. 2

    A naked type parameter distributes over unions: each member is checked separately and the results are unioned. Wrap both sides in a tuple, [T] extends [U], to turn this off.

  3. 3

    never is the empty union, so a distributive conditional over never returns never. any returns the union of both branches.

  4. 4

    Several infer X candidates in covariant positions combine into a union; in contravariant positions (function parameters) they combine into an intersection. That is how UnionToIntersection works.

  5. 5

    Template literal types multiply unions and can parse strings with infer; infer N extends number converts numeric strings into number literals.

  6. 6

    Recursive conditional types in tail position run up to about 1,000 iterations (TS 4.5+); recursion inside spreads or other types hits the depth error far sooner. Use accumulators.

  7. 7

    Inferring from an overloaded function uses its last signature, and a conditional return type on a generic function stays deferred, so returns need overloads or assertions.

Common traps

  • T extends never ? true : false returns never for never; use [T] extends [never].

  • boolean is true | false, so it splits in distributive conditionals and counts as a union.

  • Mapping over a function type (for example in a naive DeepReadonly) turns it into {} and drops its call signature.

Test yourself on Conditional, Template Literal and Recursive Types

Ten questions, with the answer and explanation after each one.