Mypy does not detect the subtype relation (correct term?) when it comes to dict values:
if False:
from typing import Union
# works
foo1 = 0 # type: int
bar1 = foo1 # type: Union[int, str]
# "Incompatible types in assignment"
foo2 = {} # type: dict[str, int]
bar2 = foo2 # type: dict[str, Union[int, str]]
Mypy 0.4.5
This is actually correct, because Dict[str, int] is not a subtype of Dict[str, Union[str, int]] (even though int is a subtype of Union[int, str]). The reason is that Dict is defined as _invariant_ in its type parameters, and that is done because Dict is mutable.
Consider this code:
a = {} # type: Dict[str, int]
def f(b: Dict[str, Union[int, str]]) -> None:
b['x'] = 'y'
f(a)
If we allowed that call to f(a), a would end up with a string value! To prevent this we don't consider Dict[str, Union[int, str]] a subtype of Dict[str, int].
Most helpful comment
This is actually correct, because
Dict[str, int]is not a subtype ofDict[str, Union[str, int]](even thoughintis a subtype ofUnion[int, str]). The reason is that Dict is defined as _invariant_ in its type parameters, and that is done because Dict is mutable.Consider this code:
If we allowed that call to
f(a),awould end up with a string value! To prevent this we don't considerDict[str, Union[int, str]]a subtype ofDict[str, int].