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
type MyExclude<T, U> = ???
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.
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
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.
? 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.