I understand the value of enforcing behaviours with types, but experience has taught me that this is a tooling issue, not something you have to wrap into a spaghetti mess every time you want to code an if.
Example: While programming kotlin, intellij idea warned me whenever I accessed a nullable object without a null check, and gave suggestions to convert types to non-nullable in order to avoid the checks altogether whenever appropriate.
I think there is value in keeping the code clean while keeping it correct at the same time, but that should be done at the compiler or linter level.
A linter or IDE can only "suggest" that you don't access null objects without a null check. You as the developer can choose to ignore the linter or IDE and write bad code anyway.
Enforcing behavior via the typing system prevents bad code from even compiling and running in the first place.
When you stop thinking of Optional<T> as a inconvenient wrapper clumsily wrapping a T and starting thinking of it as a first class datatype with its own members and methods, then it becomes a lot more clear to reason about the logic.
Example: While programming kotlin, intellij idea warned me whenever I accessed a nullable object without a null check, and gave suggestions to convert types to non-nullable in order to avoid the checks altogether whenever appropriate.
I think there is value in keeping the code clean while keeping it correct at the same time, but that should be done at the compiler or linter level.