Skip to content
webtype.orgwebtype.org#220 rebuild-exclude · par 3

    ↑↓ move · ⏎ open · esc close

    No. 220 · July 28, 2026 · Moderate

    Rebuild Exclude

    Implement `MyExclude<T, U>` so it removes from the union `T` every member assignable to `U`. It is one line — the subtlety is why that line works at all.

    01

    Try the puzzle yourself

    Par 3

    Puzzle

    rebuild-exclude.ts
    Stroke 1 of 3Not run yet

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

    Checks

    4
    • MyExclude<'a' | 'b' | 'c', 'a'>
      'b' | 'c'
    • MyExclude<string | number, number>
      string
    • MyExclude<'a', 'a'>
      never
    • MyExclude<'a' | 'b', 'c'>
      'a' | 'b'

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

    The solution

    type MyExclude<T, U> = T extends U ? never : T

    The common wrong answer

    type MyExclude<T, U> = [T] extends [U] ? never : T

    Wrapping `T` in a tuple switches distribution off, so the whole union is compared at once. `["a" | "b" | "c"] extends ["a"]` is false, and the entire union comes back unfiltered.

    Line by line

    1. T extends U

      `T` here is *naked* — it appears alone on the checked side, not wrapped in a tuple, array or object. That is the exact condition that triggers distribution over a union.

    2. ? never : T

      Each member either becomes `never` or survives as itself. Unioning the results drops the `never`s automatically, because `never` is the identity element of union.

    Takeaway

    Distribution is the difference between asking a question about a union and asking it about each member. `[T] extends [U]` is the switch that turns it off.

    Uses