On Thu, May 23, 2024, at 1:35 AM, Robert Landers wrote: > For what it's worth, the biggest downside to this decision is in > upgrading old/legacy projects to use enums. Most of the time, you want > to convert a const to an enum, and that also usually means it will be > a backed enum. Since there's no way to cast a backed enum to a > string/int, you have to instead add ->value (I really don't understand > the difference; casting would have been much more elegant); this > almost always results in lots of hidden runtime errors. At the last > couple of places, after seeing the damage the conversion could do, > doing this conversion was simply off-limits. Maybe by now, there is > some reliable tooling to handle this automatically... I haven't > looked. The point remains that it is a strange decision to use > `->value` but not allow `(string)` or `(int)` or allow even > implementing it yourself.
Union types are the correct solution here: function move(string $direction, Player $player) { ... } becomes function move (Direction|string $direction, Player $player) { if (is_string($direction)) { $direction = Direction::from($direction); } // We now have a normalized enum to work with. } The only catch there is inheritance, where it works fine if you jut expand the implementers/children first, then the interface/parent. Then you can remove the string option at some point in the future, going the other way (interface/parent, then implementer/child). --Larry Garfield