Typing Usability Overhaul · Issue #496 · python/typing (original) (raw)

While I am a big proponent of static typing, I always found typing, the module, clunky. And typing_extensions? That thing I just hate, it's a usability disaster. In an ideal world, people wouldn't need those extra modules, at least not for the common things they want to do. How can we get there?

Accept PEP 563

It lets people get away with not having a runtime typing for annotations. Read below for edge cases.

Split typing

The goal here is to minimize the need for people to import from typing at all.

Move NamedTuple to collections

It always belonged there.

We need TYPE_CHECKING in the interpreter

Let's call it __typing__. That way we can really remove the need for a runtime typing module, unless somebody creates generic classes. Thanks to PEP 563 that would be the new idiom:

if __typing__:
    from typing import *
    T = TypeVar('T')
    UserId = NewType('UserId', int)
    ...  # etc.

def f(users: List[UserId]) -> Optional[UserId]:
    ...

For context, I would rename TYPE_CHECKING to __typing__ just like __debug__ because I would also like to be able to flip the switch to be True with a command-line option/env variable to Python. That is required to make people wanting runtime type checking happy.

cast() needs to change

I suggest this syntactic change so that we don't need to add it to Python's builtins:

# reveal_type(previous_result) is `builtins.int`
result: cast(UserId) = previous_result

That way we don't actually cast anything at runtime, there's no function call. While it doesn't compose to random expressions and you need a new artificial name for this, I find this an improvement.

get_type_hints() needs to move to inspect

Untying it from the logic in typing will be a bit of a challenge but this is required if PEP 563 is to be accepted at all. We need a blessed way in Python proper to evaluate annotations at runtime.

ABCs belong in collections.abc

It always felt ugly to me that we have separate typing equivalents for collections. Builtin types, that I get, but having a separate Counter, and better yet, MutableMapping, that feels wrong.

I would add generics support to collections directly and make typing just mirror those real classes in 3.7+ for backwards compat. The damage is already done, people will try to import those types from typing.

The rest goes to a PyPI module called typing

This includes the current and future contents of typing_extensions and ideally also mypy_extensions.

PEP 563 deep dive

For now, if __typing__: from typing import * will do. But that's clunky and wordy. In the future, PEP enables more friendly syntax that doesn't require typing at all, like list[str], collections.Mapping[int, int], any, str or None, etc. This needs a separate PEP and a ton of bike-shedding, but if the point is to make type annotations feel more first-class, we need to acknowledge that we can and should improve the common case to be more obvious to users.

What if you really need typing at runtime?

That's okay. If you subclass generics, or want to use any other thing that cannot be put in annotations or if __typing__:, then add typing to your requirements.txt and import it as a regular module.