After learning about TYPE_CHECKING
i made it a habit to put all imports that were only needed for type checking into an if TYPE_CHECKING:
guard. But now I am wondering if that is actually intended to be used like that. Checking whether an import is only needed at type checking time can get quite tedious and sometimes you run into situations were you introduced some code that made the import a requirement at runtime.
How do you use TYPE_CHECKING
? Whenever it is possible or only when using it actually solves a circular import?
I don’t like having to quote the types, so I use it exclusively for avoiding circular imports.
from __future__ import annotations
I only use it to avoid circular imports. Otherwise, I can import the type plainly.
Any time you need different behavior between static type checking and runtime.
in 3.10 I’m using it to work around issue with NamedTuple generics. typing_extensions.NamedTuple allows Generics at runtime but typing.NamedTuple doesn’t. But the type checker we are using doesn’t support typing_extensions.NamedTuple like it does for the typing version so we lie at type checking time to get the typing to make sense but have different runtime type because otherwise its a TypeError