While this code works:
from typing import TypeAlias, TypeVar
T = TypeVar("T", complex, float, str)
z: TypeAlias = tuple[T, ...] | list[T]
defining T
conditionally does not.
from typing import Generic, TypeAlias, TypeVar
try:
import somepackage
use_complex = True
except:
use_complex = False
if use_complex:
T = TypeVar("T", complex, float, str)
else:
T = TypeVar("T", float, str)
z: TypeAlias = tuple[T, ...] | list[T]
I am getting: Variable not allowed in type expression
Is there a way to tell the typechecker that use_complex is a constant and therefore it is either one branch or the other, T
is defined only once and does not change?
mypy and Pyright1 both support defining compile-time constants to enable control flow analysis like this; the behaviour is similar to sys.version_info
, sys.platform
, or typing.TYPE_CHECKING
guards.
Put the following in your mypy configuration file:
[mypy]
# Only specify ONE of the following:
# * When developing against the package
always_true = use_complex
# * When not developing against the package
always_false = use_complex
Then do one of the following:
Define the constant in a dedicated module
# constants.py
try:
import somepackage
use_complex = True
except:
use_complex = False
>>> import constants
>>>
>>> if constants.use_complex: ...
... ...
Define the constant in the same module and use it. This is the same as your example in the question (mypy playground demo: always_true = use_complex
, always_false = use_complex
)
try:
import somepackage
use_complex = True
except:
use_complex = False
if use_complex:
T = TypeVar("T", complex, float, str)
else:
T = TypeVar("T", float, str)
z: TypeAlias = tuple[T, ...] | list[T]
num: z[complex] = [8j] # OK when `always_true = use_complex`, else errors when `always_false = use_complex`
During development, you'd just change your configuration file to switch between the use_complex
modes.
Note that the try...except
doesn't actually do anything for mypy here, that's only for your runtime behaviour.
defineConstant
configuration of https://github.com/microsoft/pyright/blob/main/docs/configuration.md