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

Generic TypedDict and inferring return value #17753

Open
patrick91 opened this issue Sep 10, 2024 · 1 comment
Open

Generic TypedDict and inferring return value #17753

patrick91 opened this issue Sep 10, 2024 · 1 comment
Labels
bug mypy got something wrong

Comments

@patrick91
Copy link
Contributor

patrick91 commented Sep 10, 2024

I was working on some code that needs to be passed a generic TypedDict, like this:

from typing import TypeVar, TypedDict, Generic

T = TypeVar("T")

ReturnValue = TypeVar("ReturnValue")


class Option(TypedDict, Generic[ReturnValue]):
    name: str
    value: ReturnValue


class Menu:
    def ask(self, text: str, options: list[Option[T]]) -> T:
        return options[0]["value"]

And the usage would be this:

value = Menu().ask("text", [{"value": 123, "name": "abc"}])

reveal_type(value)

In this case the value type should int, but unfortunately I get this error:

main.py:18: error: Need type annotation for "value"  [var-annotated]
main.py:18: error: Argument 2 to "ask" of "Menu" has incompatible type "list[dict[str, int]]"; expected "list[Option[Never]]"  [arg-type]

Playground: https://mypy-play.net/?mypy=latest&python=3.12&flags=verbose%2Cstrict&gist=9a8643b51a69f6d60ab5b0b482e10865

This seems to be working well in pyright 😊

Also I didn't find yet a workaround, changing the class to this:

class Menu:
    def ask(self, text: str, options: list[dict[str, T]]) -> T:
        return options[0]["value"]

Almost works, but for example in the case above it would infer the type as object 😊

@patrick91 patrick91 added the bug mypy got something wrong label Sep 10, 2024
@patrick91
Copy link
Contributor Author

Ah! Found a workaround, full code:

from typing import TypeVar, TypedDict, Generic

T = TypeVar("T")

ReturnValue = TypeVar("ReturnValue")


class Option(TypedDict, Generic[ReturnValue]):
    name: str
    value: ReturnValue


class Menu:
    def ask(self, text: str, options: list[Option[T]]) -> T:
        return options[0]["value"]
        

value = Menu().ask("text", [Option({"value": 123, "name": "abc"})]) # 👈 this is the workaround, passing the typed dict instead of a "generic" dict

reveal_type(value)

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

No branches or pull requests

1 participant