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

Completion does not work for generic type aliases #1698

Open
pappasam opened this issue Nov 19, 2020 · 5 comments
Open

Completion does not work for generic type aliases #1698

pappasam opened this issue Nov 19, 2020 · 5 comments
Labels

Comments

@pappasam
Copy link
Contributor

pappasam commented Nov 19, 2020

Generic type aliases are not currently supported for autocompletion. For context, for a codebase I'm developing, I'm working with a generic type alias that helps me handle TypeScript interface undefined values (which differ from null, a value that corresponds to Python's None).

See below for a simple example of the problem.

from dataclasses import dataclass
from typing import TypeVar, Union

T = TypeVar("T")

MyType = Union[None, T]

d = {"t": "hello"}

@dataclass
class MyDataclass:

    t: MyType[str]

result = MyDataclass(**d)
result.t.

To remain consistent with jedi's behavior concerning Union types, this should provide completions for both string and None, but it completes nothing with version 0.17.2. For comparison, things work fine for Optional, which is basically a special case of Union[None, T]:

from dataclasses import dataclass
from typing import Optional

d = {"t": "hello"}

@dataclass
class MyDataclass:

    t: Optional[str]

result = MyDataclass(**d)
result.t.
@PeterJCLaw
Copy link
Collaborator

Thanks for the report, however unfortunately I think you've hit one of the limitations of Python type annotations themselves rather than Jedi specifically.

The limitation is that user defined generic aliases (such as your MyType) do not preserve their generic nature, so in fact your MyType alias is in fact equivalent to Optional[Any].

You can see this in action if you add in a reveal_type(MyType) or reveal_type(MyType[str]) and then type-check using either mypy or pyre-check.

I'm pretty sure this is an known issue with the type system, though I can't find an exact reference for it.
There are a couple of mypy issues which are similar though: python/mypy#7092 and python/mypy#7084.

@pappasam
Copy link
Contributor Author

pappasam commented Nov 28, 2020

Hmm, I'm not completely understanding your point. User defined generic aliases appear to be supported by mypy and type checking the above example works as expected with mypy (version 0.790). Try changing example 1 to be:

from dataclasses import dataclass
from typing import TypeVar, Union

T = TypeVar("T")

MyType = Union[None, T]


@dataclass
class MyDataclass:

    t: MyType[str]


a = MyDataclass(t=None)
b = MyDataclass(t="hello")
c = MyDataclass(t=12)

and observe that mypy now returns:

test.py:17: error: Argument "t" to "MyDataclass" has incompatible type "int"; expected "Optional[str]"
Found 1 error in 1 file (checked 1 source file)

This indicates that mypy is understanding the generic type alias as-intended.

I do see that reveal_type returns builtins.object for MyType, but it seems like it does that for any Union type.

@PeterJCLaw
Copy link
Collaborator

Huh, looks like you're right. I was fairly sure that this didn't work in the past, though I agree it definitely does now.

@davidhalter
Copy link
Owner

@PeterJCLaw Interested in solving this? Seems like something tailored for you :)

@PeterJCLaw
Copy link
Collaborator

Looks like this is possible with Callable too, which Jedi also doesn't support:

from typing import Callable, TypeVar
T = TypeVar('T')
MyCallable = Callable[..., T]
x: MyCallable[str]
x().<nothing>

I suspect the fix for Callable is slightly different, though potentially also worth fixing.

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

No branches or pull requests

3 participants