I figured it was relevant, since it relates to types as a whole.
Consider the following: I have a "rating" type, which is a whole number from 0 to 5. If you try rendering a view with a number outside of that range, that's a bug! Which means you probably made a mistake somewhere.
I want software to help me catch bugs. If something can't be confirmed with a linter or compiler, getting a good error message during runtime is also fine. Once I've established that I expect some value, I don't want to write extra checks to confirm that my expectations are met.
It relates to typing as a method of encoding invariants, yes. I was trying to say that it is unrelated to which "type" of typing. That is, I can perfectly imagine a statically typed language where you could encode such restrictions as easily as you do with Elixir and you would get the same result, a runtime error.
Regarding your rating example, you could encode that restriction in a type (or class in OO) and have a guarantee that once you have an instance of that type you no longer need to check for it's validity. Rendering a Rating would never fail at runtime, you'd get a type error first.
It is usually still considered part of type checking. It's basically adding ranges to the types. For instance, `sin` will always return `float[-1, 1]`. If I have a function that takes `float[-10, 10]`, they're compatible. If my function takes `float[10, 20]`, then they're not compatible.
Consider the following: I have a "rating" type, which is a whole number from 0 to 5. If you try rendering a view with a number outside of that range, that's a bug! Which means you probably made a mistake somewhere.
I want software to help me catch bugs. If something can't be confirmed with a linter or compiler, getting a good error message during runtime is also fine. Once I've established that I expect some value, I don't want to write extra checks to confirm that my expectations are met.