Just in case you are not aware of this:
PHP added Enum (https://www.php.net/manual/en/language.enumerations.basics.php) in 2020, which aims to cover the same problem you are mentioning but natively.
Although ValueObjects have a meaning and reason to exist, this example is (only) helpful for PHP versions before version 8.1, when it was added. After that, Enums should be the way to solve the problem you have exposed.
PHP Enums can be set to handle integers, strings, and booleans… they are immutable (because you can't change the value of that enum object; you can only replace it), and it's safe to consider them a Singleton (meaning we don't use more memory than the bare minimum we need).
The main difference between an Enum and a ValueObject is that Enums are value representations in an object format. Still, ValueObjects are more advanced because they (may) have logic and behaviour and represent a business concept (that's why you mentioned assertions and checks).
Furthermore, Enums implements the Open-Closed Principle to add methods that open them to extension and make them more powerful ValueObjects per se.