Hacker News new | past | comments | ask | show | jobs | submit login

The way to think about gradual type annotations is not like types in C. You're not saying "this variable is 8 bytes that we're going to interpret as a floating point number." What they do is let you express constraints on the behavior of your program, and then run another program to check whether those constraints have been violated.

Suppose you start with the function

    def foo(bar, baz):
        if bar > baz > 0:
            return bar / baz
        return "bar is not bigger"
And this is what you want the function to do, for some reason. But by the time you start writing other code, you've forgotten about the unusual "bar is not bigger" case, and you just assume you're always getting a number back. This could turn into a runtime exception somewhere else in your code because a field in some object somewhere now has a value of the wrong type, but you've never run into it so you don't know about the ticking time bomb.

Now you start adding type annotations to foo:

    def foo(bar: float, baz: float) -> float:
        ...
And when you check the types, mypy yells at you, and you realize you actually need to write this:

    def foo(bar: float, baz: float) -> Union[float, str]:
        ...
At this point mypy starts informing you about all the places you failed to handle the "bar is bigger" return value, and you go and fix them. You keep going until all of the constraints you've put on your code are consistent. You don't have to completely type everything for this to be useful, nor is it particularly important to check this stuff at runtime, because all mypy is doing is telling you that the code you've written satisfies the assumptions you're telling it about.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: