Skip to content
webtype.org#223 type-level-subtract · par 5

No. 223 · July 31, 2026 · Brutal

Type-level Subtract

Implement `Subtract<A, B>` returning `A − B` as a number literal. When `B` is larger than `A` the answer is `never` — there are no negative tuple lengths.

01

Try the puzzle yourself

Par 5

Puzzle

type-level-subtract.ts
type BuildTuple<N extends number, Acc extends unknown[] = []> =
  Acc['length'] extends N ? Acc : BuildTuple<N, [...Acc, unknown]>
Stroke 1 of 5Not run yet

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

Checks

4
  • Subtract<5, 3>
    2
  • Subtract<3, 3>
    0
  • Subtract<10, 4>
    6
  • Subtract<2, 5>
    never

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 1, 2026

The solution

type Subtract<A extends number, B extends number> =
  BuildTuple<A> extends [...BuildTuple<B>, ...infer Rest] ? Rest['length'] : never

The common wrong answer

type Subtract<A extends number, B extends number> =
  [...BuildTuple<A>, ...BuildTuple<B>]['length']

That is addition wearing a different name. Concatenating the two tuples can only ever make them longer; subtraction has to take a tuple *apart*, which means pattern-matching rather than building.

Line by line

  1. [...BuildTuple<B>, ...infer Rest]

    The pattern hard-codes a prefix of exactly `B` elements and lets `Rest` absorb whatever is left. Matching succeeds only when the subject is at least that long.

  2. : never

    When `B > A` there is no way to line up the prefix, the conditional fails, and `never` falls out — which is the honest answer for a subtraction this arithmetic cannot represent.

Takeaway

Building tuples adds; destructuring them subtracts. Every arithmetic operation TypeScript can do at the type level is one of those two motions in disguise.