> domain SymfonyPermission: string; > domain AcmePermission: string { 'admin' | 'user' | 'bot' }; > [...] > Domains can also be considered sets, which you could compare directly, > and maybe even calculate intersections, unions, etc: > > The actual values would be ordinary strings, and type constraints would > just be checking the value passed against the domain: > > Crucially, this solves the described problem of a library accepting an > infinite (or perhaps just very wide) set of values, and a consuming app > wanting to constrain that set within its own code. > > It's one disadvantage is the typo-proofing and look up availability that > constants give, but you could always combine the two. >
Thanks for this idea Rowan, that's really interesting. I would go one step further and require naming the values in the set. Borrowing from the syntax of enums, we could have: set AcmePermission: string { case ADMIN = 'admin'; case USER = 'user'; case BOT = 'bot'; } Then AcmePermission::ADMIN would === 'admin' and, as you said, AcmePermission could be used as a type on functions: function (AcmePermission $perm): AcmePermission { $perm instanceof AcmePermission; // true return $perm; } In order to make this work, we would need to be able to autoload the type AcmePermission.This could be done by the type-checking logic: when checking $var against AcmePermission and the type is undefined, if $var is an int or a string, call the autoloader for 'AcmePermission'. There are other things to consider, like possible changes to reflection, whether such a set also declares a class like enums do, etc.But overall, I really like it and I agree with you: this would provide a really good solution for the problem ppl try to use enums for. I don't know how we could move forward on that idea. By starting another thread? Nicolas