Comment by OptionOfT
In general I'm a huge favor of using the type system to its fullest extend to protect you from messing up. If the compiler can protect me, it should.
Examples where I've used it in the past: ValidatedEmail, which is a special form of Email, one that has been validated by the user.
We can have actions that require a `PriviligedUser`, which can be created from a `User`. That creation validates ONCE whether your user is privileged.
This saves you from a whole bunch of .is_priviliged() calls in your admin panel.
The post 'Boolean Blindness' [0] talks about much of the same issues.
[0]: https://existentialtype.wordpress.com/2011/03/15/boolean-bli...
I'm a big proponent of using types, but my experience with "Validated" types has not been positive. It's nice when it's unambiguous, but adding "validated" to the name of a type can mean almost anything. What has been validated? Validated according to what rules? You can add what has been validated to the type name, like I can tell that ValidatedNonnegativeInt is a nonnegative integer, but NonnegativeInt would tell me the same thing more concisely.
I've also had a negative experience with using types to encode privileges. Types work well in simple situations, but they scale very badly with additional complexity. Something like PrivilegedUser works fine as long as privilege is binary and one-dimensional, but the need for new types will very quickly grow out of hand for only a modest increase in the complexity of requirements. Encoding privileges as data handles a combinatorial explosion of possibilities much more gracefully, and it is much more straightforward for checking rules that are stored outside the codebase.