Skip to content
webtype.org#229 flatten-tuple · par 4

No. 229 · August 6, 2026 · Hard

Flatten

Implement `Flatten<T>` so it flattens a nested tuple completely, to any depth.

01

Try the puzzle yourself

Par 4

Puzzle

flatten-tuple.ts
Stroke 1 of 4Not run yet

Replace ??? — your solution is checked against the cases below. Tab indents; press Escape then Tab to move focus out.

Checks

4
  • Flatten<[1, [2, 3], 4]>
    [1, 2, 3, 4]
  • Flatten<[]>
    []
  • Flatten<[[[1]]]>
    [1]
  • Flatten<[1, [2, [3, [4]]]]>
    [1, 2, 3, 4]

How a check is judged Exact type equality, not assignability — an intersection is not the same as the flattened object.

How everyone did

Fewer than 5 people have solved this one so far. The distribution appears once there is enough of a sample to mean anything.

Archive
02

Annotated solution

Published August 7, 2026

The solution

type Flatten<T extends readonly unknown[]> =
  T extends readonly [infer H, ...infer R]
    ? H extends readonly unknown[]
      ? [...Flatten<H>, ...Flatten<R>]
      : [H, ...Flatten<R>]
    : []

The common wrong answer

type Flatten<T extends readonly unknown[]> =
  T extends readonly [infer H, ...infer R]
    ? H extends readonly unknown[]
      ? [...H, ...Flatten<R>]
      : [H, ...Flatten<R>]
    : []

Spreading `H` directly unwraps exactly one layer, so `[[[1]]]` flattens to `[[1]]` and stops. The head must be flattened recursively too — it is not merely a container to open, it is a whole nested structure.

Line by line

  1. H extends readonly unknown[]

    The branch that decides whether this element needs opening. `readonly unknown[]` matches both mutable and readonly tuples, so neither is accidentally treated as a scalar.

  2. [...Flatten<H>, ...Flatten<R>]

    Two recursive calls, one going down into the nesting and one going along the tuple. That pair is what makes the flattening total rather than single-level.

Takeaway

Recursing in one direction walks a list; recursing in two walks a tree. Most "it only went one level deep" bugs are a missing second recursive call.