An amazing read, and almost perfect!
There's a bug in the Solve "function" due to which you'll get the right answer only for 1x1, 5x5 and 7x7 (I checked till 8x8).
The base case makes a wrong assumption that there will always be a candidate available for the last row. If there are no candidates available, it should return Nil, and backtrack.
Basically, replace
Concat<candidates, placedQueens>
with candidates extends Cons<infer x, any>
? Cons<x, placedQueens>
: Nil