Skip to content
webtype.orgwebtype.org#217 split-string · par 4

    ↑↓ move · ⏎ open · esc close

    No. 217 · July 25, 2026 · Hard

    Split

    Implement `Split<S, D>` so it splits the string `S` on every occurrence of the delimiter `D`, returning a tuple of the pieces. A string with no delimiter yields a one-element tuple.

    01

    Try the puzzle yourself

    Par 4

    Puzzle

    split-string.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
    • Split<'a,b,c', ','>
      ['a', 'b', 'c']
    • Split<'nope', ','>
      ['nope']
    • Split<'a/b', '/'>
      ['a', 'b']
    • Split<'', ','>
      ['']

    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.

    Short game

    Fewest characters

    No public scores yet.

    Archive
    02

    Annotated solution

    Published July 26, 2026

    The solution

    type Split<S extends string, D extends string> =
      S extends `${infer Head}${D}${infer Tail}` ? [Head, ...Split<Tail, D>] : [S]

    The common wrong answer

    type Split<S extends string, D extends string> =
      S extends `${infer Head}${D}${infer Tail}` ? [Head, Split<Tail, D>] : [S]

    Without the spread, each recursive result is nested one level deeper: `["a", ["b", ["c"]]]`. The `...` is what flattens the recursion into a single tuple.

    Line by line

    1. `${infer Head}${D}${infer Tail}`

      Inference against a template literal is greedy from the left, so `Head` binds the shortest prefix that lets the rest of the pattern match — giving you the first field, not the last.

    2. [Head, ...Split<Tail, D>]

      The spread inlines the recursive tuple, so each level contributes one element to a flat result.

    3. : [S]

      No delimiter left. The whole remaining string is the final piece, wrapped in a tuple so the spread above has something to inline.

    Takeaway

    Recursive string types decompose head-first and rebuild with spreads. Forgetting the spread is the single most common bug in type-level list building.

    Uses