Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Types that should match the alias definition don't #2

Open
smheidrich opened this issue Nov 18, 2022 · 4 comments
Open

Types that should match the alias definition don't #2

smheidrich opened this issue Nov 18, 2022 · 4 comments

Comments

@smheidrich
Copy link

The issue from python/mypy#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.

@endrift
Copy link

endrift commented Jul 27, 2023

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

@kyle-query
Copy link

kyle-query commented Dec 6, 2023

@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.

@endrift
Copy link

endrift commented Dec 6, 2023

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.

@kyle-query
Copy link

kyle-query commented Dec 6, 2023

True, it could be a limitation of mypy. It will work with pyright for certain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants