Do you try to use some existing Board type and just avoid in your algo those invalid states (like by using a stack or some data structure to avoid iteratively moving pieces one at a time).
Do you have a separate InvalidBoard type that allows multiple pieces per square?
I think it’s context dependent but I’m curious how you’ve seen this handled in different ways.
A niche example of this kind of thing is when solving commercial/industrial combinatorial optimisation problems. Maybe the goal is to maximise profit or minimise capex subject to a large number of constraints. Sometimes it is intractable to solve the true problem, but there's some approximation of the problem by relaxing one or more constraints that's much easier to solve. In some of these business contexts its completely OK if the optimiser ran overnight before spitting out a solution, provided it found a 5% better one. In that setting it'd be natural to decouple the internal representation(s) of a black box optimiser from the high-level way you represent the true problem & its solutions elsewhere in the system.
Some of these systems might end up feeling a little like a compiler toolchain - high level descriptions of problems & solutions that get transformed into / recovered from lower level implementation-specific representations.
If your context has high performance needs, e.g. needing to solve the problem 30 times per second in a real-time game or control system, or react as quickly as possible in a low-latency trading system, maybe it could be less of a good tradeoff to introduce avoidable copying of data between a strict correct representation & a relaxed representation. Could write the clean thing first & then profile and see if the overhead of copying is relevant. If the representation of your solution is small, there probably isn't that much overhead in copying it, unless your performance needs are extreme or your hardware is severely limited.