Types that should match the alias definition don't
The issue from https://github.com/python/mypy/issues/13786 applies to the type alias from this package as well: For something like
from jsonalias import Json
def f(j: Json):
pass
d: dict[str, str] = { "a": "b" }
f(d)
Mypy will complain
example.py:8: error: Argument 1 to "f" has incompatible type "Dict[str, str]"; expected "Json" [arg-type]
example.py:8: note: "Dict" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
example.py:8: note: Consider using "Mapping" instead, which is covariant in the value type
Found 1 error in 1 file (checked 1 source file)
despite dict[str, str] clearly being expected to match the definition of the type alias.
In the comments on the aforementioned issue, there is a suggestion to use typing.Sequence and typing.Mapping instead of list and dict like the error message suggests, which does solve this issue, but comes with issues of its own because one often genuinely only wants dicts and lists to count as JSON-like, not generic mappings and sequences.
No idea what to do (or if anything should be done at all at this point, other than waiting for new features in Mypy or Python's typing), just pointing out that there is an issue here.
Edit: My mistake, I thought this was the mypy repo while following links. I think it's a mypy bug.
Original comment:
I am also having as similar issue, where if I try to assign or return a type e.g. List[str] it will say it isn't compatible:
Jsonable = Union[bool, float, int, str, list['Jsonable'], dict[str, 'Jsonable'], None]
And I get e.g. this error:
error: Incompatible types in assignment (expression has type "List[str]", target has type "Jsonable") [assignment]
Using mypy 1.3.0 on Python 3.11.3
@endrift This is due to type variance on the type arguments to list[T] or dict[K, V]. Because these are mutable containers, they have invariant type parameters. For instance, list[int] is not a subtype of list[object]. In this particular case, it means list[str] is not a subtype of list[Union[bool, float, int, str, ...]].
For this to work like you want, the type definitions need to use something with covariant type arguments. If the definition was changed to
from typing import Sequence, Union, Mapping
Jsonable = Union[int, str, float, bool, Sequence["Jsonable"], Mapping[str, "Jsonable"]]
then this will work
x: list[str] = ["hi"]
y: Jsonable = x
because list[str] is a subtype of Sequence[Union[str, int, ...]] which is a subtype of Jsonable.
While I appreciate your help with my obviously off-topic issue, I'm pretty sure at some point I tried that and it only partially alleviated the issue. I don't quite remember because I haven't touched that code in a few months. I do remember stumbling upon a documented mypy limitation at some point though, but that might have been something more complicated.
True, it could be a limitation of mypy. It will work with pyright for certain.