mypy --strict
dutifully complains about the following code:
from typing import Any, Dict
def main() -> None:
my_str: str = 'hello'
my_int: int = my_str
if __name__ == "__main__":
main()
by outputting:
error: Incompatible types in assignment (expression has type "str", variable has type "int")
However the following code is accepted without any error:
from typing import Any, Dict
def main() -> None:
my_str: Any = 'hello'
my_int: int = my_str
if __name__ == "__main__":
main()
Is there an option for mypy
to make it also reject the second example?
I expect it to do so, because it also rejects the following:
from typing import Any, Dict, Union
def main() -> None:
my_str: Union[int, str] = 'hello'
my_int: int = my_str
if __name__ == "__main__":
main()
with:
error: Incompatible types in assignment (expression has type "Union[int, str]", variable has type "int")
And in my understanding an Any
is just the Union
of all possible types.
For those that read about this later, the actual solution is to use the "disallow any" family of command line flags, as describes in this answer.
That's not correct.
Any
is an escape hatch, an annotation for variables that you want the type checker to ignore. It certainly is not a union.From the mypy documentation on
Any
:(Bold emphasise mine)
It explicitly covers your case:
So the correct approach is to not use
Any
if you want the type checker to keep tracking how the value is used. Use aUnion[]
, as you did in your third example, or re-think your data structures to allow for better type hinting. For example, rather than use a dictionary with a union value type, consider using a named tuple or dataclass with explicit fields and a specific type for each field.