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

Type narrowing on TypedDict with match expresion produces an unexpected error #16834

Open
rlkandela opened this issue Jan 29, 2024 · 3 comments
Labels
bug mypy got something wrong

Comments

@rlkandela
Copy link

Bug Report

When you try to narrow down the type of a TypedDict by checking with a match expression, it produces an error when it shouldn't. But when you try an equivalent code but instead of using match, using if/else it works as expected.

To Reproduce

from typing import TypedDict, Literal, Union

class EmptyTaskPayload(TypedDict):
    pass

class CheckPendingTaskSystemRebootResponse(TypedDict):
    type: Literal["SYSTEM/REBOOT"]
    payload: EmptyTaskPayload
    
class SystemVersionTaskPayload(TypedDict):
    version: str
    
class CheckPendingTaskSystemVersionResponse(TypedDict):
    type: Literal["SYSTEM/VERSION"]
    payload: SystemVersionTaskPayload

CheckPendingTaskResponse = Union[
    CheckPendingTaskSystemRebootResponse,
    CheckPendingTaskSystemVersionResponse
]

def test_match(pending_task: CheckPendingTaskResponse) -> None:
    match pending_task["type"]:
        case "SYSTEM/REBOOT":
            pass
        case "SYSTEM/VERSION":
            payload = pending_task["payload"]
            version = payload["version"]
#                                      ^ Error produced here
# main.py:28: error: TypedDict "EmptyTaskPayload" has no key "version"  [typeddict-item]

def test_if(pending_task: CheckPendingTaskResponse) -> None:
    if pending_task["type"] == "SYSTEM/REBOOT":
        pass
    elif pending_task["type"] == "SYSTEM/VERSION":
        payload = pending_task["payload"]
        version = payload["version"]

Code with inlay hints
Error given in the local editor
Playground and Gist

Expected Behavior

Expected the code to be absent of errors since it's correct.

Actual Behavior

Produces an error in the index of payload with the key "version" saying that the other type (EmptyTaskPayload) does not have that key. Which is strange as the type system givs payload the correct type (SystemVersionTaskPayload) and in the alternative version with if/else it works.

Your Environment

  • Mypy version used: 1.8.0
  • Python version used: 3.10.12
@rlkandela rlkandela added the bug mypy got something wrong label Jan 29, 2024
@erictraut
Copy link

I don't think mypy currently supports discriminated unions of TypedDicts for pattern matching, so this isn't really a bug. It's a reasonable feature request, however. FWIW, pyright supports this feature.

@rlkandela
Copy link
Author

Shall I close this issue and open a feature request?

@tmke8
Copy link
Contributor

tmke8 commented Jan 29, 2024

I think this is the same as #16286. Your issue title is maybe better though.

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

3 participants