Moving TYPE_CHECKING out of typing and into the built-in namespace

With the acceptance of PEP 563 and its soon-to-be-default status, I was thinking that maybe typing.TYPE_CHECKING could be made a built-in name to allow for situations where typing would not have to be imported at all at runtime. This would work well in code that is only using simple type hints that doesn’t need access to any of the functions in typing.

Consider the following toy example:

from __future__ import annotations
from typing import TYPE_CHECKING, Union, Tuple

if TYPE_CHECKING:
    from circular.module import circular_import

class A():
    def __init__(self) -> None:
        pass


    def spam(x: circular_import) -> A:
        return x.spam()


    def eggs(x: int) -> Union[Tuple[int,int], Tuple[str,str]]:
        ...

With the annotations as strings, that means we’re not actually using Union and Tuple at runtime. We could move those imports into the if TYPE_CHECKING block like so:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from typing import Union, Tuple
    from circular.module import circular_import

but then we have multiple from typing import statements and we still have to import the whole typing module just to get TYPE_CHECKING. If TYPE_CHECKING was always available, we could have code like this in a future Python:

if TYPE_CHECKING:
    from typing import Union, Tuple
    from circular.module import circular_import

class A():
    def __init__(self) -> None:
        pass


    def spam(x: circular_import) -> A:
        return x.spam()


    def eggs(x: int) -> Union[Tuple[int,int], Tuple[str,str]]:
        ...




What do you think? Is this worthwhile or is it a premature optimization?

3 Likes

It is possible to guard the imports with something other than typing.TYPE_CHECKING. See, for example, this question on StackOverflow.

For mypy there are a couple of other approaches discussed at Common issues and solutions — Mypy 0.812 documentation . I assume other type checkers (pytype, pyright etc.) have similar settings.

I agree with the concept, but perhaps it needs to be a name less likely to be in use, for example __type_checking__ (as dunder names are generally reserved anyhow).

PyCharm doesn’t have an elegant way of running typing code which is skipped at runtime outside of typing.TYPE_CHECKING (it complains about code inside if False blocks).

Interesting. I had seen those if False blocks before but was confused by them.

That’s also pretty surprising that mypy still parses the code even though it would never run normally.