Comment by epolanski
I couldn't care less about mathematics, but I do care about making impossible state impossible and types documenting the domain.
If you type some state as:
isLoading: boolean
result: Foo
hasError: boolean
errorMessage: string | null
then you're creating a giant mess of a soup where the state of your program could have a result, be loading and an error at the same time. If you could recognise that the state of your program is a sum of possible states (loading | success | error), and not their product as the type above you could highly simplify your code, add more invariants and reduce the number of bugs.And that is a very simple and basic example, you can go *much* further, as in encoding that some type isn't merely a number through branded types, but a special type of number, be it a positive number between 2 and 200 or, being $ or celsius and avoiding again and entire class of bugs by treating everybody just as an integer or float.