See also the type-state pattern. It is commonly used in Rust along with the builder pattern [1]. Quoting:
"""The typestate pattern is an API design pattern that encodes information about an object’s run-time state in its compile-time type. In particular, an API using the typestate pattern will have:
- Operations on an object (such as methods or functions) that are only available when the object is in certain states,
- A way of encoding these states at the type level, such that attempts to use the operations in the wrong state fail to compile,
- State transition operations (methods or functions) that change the type-level state of objects in addition to, or instead of, changing run-time dynamic state, such that the operations in the previous state are no longer possible.
This is useful because:
- It moves certain types of errors from run-time to compile-time, giving programmers faster feedback.
- It interacts nicely with IDEs, which can avoid suggesting operations that are illegal in a certain state.
- It can eliminate run-time checks, making code faster/smaller."""
Some other languages can do it as well: see [2] for a discussion.
[1]: https://cliffle.com/blog/rust-typestate/
[2]: https://www.reddit.com/r/rust/comments/17l8eez/is_there_any_...
The type-state pattern is really just OOP implementation inheritance in a type-theoretic trench coat. The relevant difference is simply that most uses of type-state are not trying to span multiple modules like the OOP design approach does; the "state" variations are contained such that they don't impact modularity throughout the program, unlike the OOP inheritance approach.