Type narrowing on TypedDict with match expresion produces an unexpected error
Nessuno ha ancora preso questa issue.
- Lingua principale
- Python
- Stelle
- 20.6k
- Fork
- 3.3k
- Metriche di merge delle PR
- Metriche PR in attesa
Descrizione
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"]
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
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Esegui la riproduzione TypedDict fornita con la versione di mypy indicata, confrontando i casi match e if/else. Traccia il comportamento del restringimento dei tipi basato su match e aggiungi un test di regressione per l'esempio; il lavoro è completato quando il ramo match restringe payload a SystemVersionTaskPayload senza un TypedDict key error.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python
- Ambito
- devtools
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 38/100