Skip to content

tagged union of unions #9308

Closed
Closed
@euri10

Description

@euri10

Report Type: Bug

Example: https://mypy-play.net/?mypy=latest&python=3.8&gist=529e99849ebe65749d8568b743f21050

I saw #8925.

It could be seen as a duplicate, not sure about it, but this one looks slightly different and more general as the one linked above, it's not only about None in unions but more about unions of unions where mypy has difficulties to narrow the correct TypedDict

from typing import Literal, TypedDict, Union

class NewJobEvent(TypedDict):
    tag: Literal["new-job"]
    job_name: str
    config_file_path: str

class CancelJobEvent(TypedDict):
    tag: Literal["cancel-job"]
    job_id: int

class AnotherOne(TypedDict):
    tag: Literal["another"]
    another: int


Event = Union[NewJobEvent, CancelJobEvent]

AnotherUnionEvent = Union[Event, AnotherOne]

event: Event
if event["tag"] == "new-job":
    reveal_type(event)
else:
    reveal_type(event)
    

another_union_event: AnotherUnionEvent
if another_union_event["tag"] == "new-job":
    reveal_type(another_union_event)
else:
    reveal_type(another_union_event)
  • What is the actual behavior/output?
main.py:23: note: Revealed type is 'TypedDict('main.NewJobEvent', {'tag': Literal['new-job'], 'job_name': builtins.str, 'config_file_path': builtins.str})'
main.py:25: note: Revealed type is 'TypedDict('main.CancelJobEvent', {'tag': Literal['cancel-job'], 'job_id': builtins.int})'
main.py:30: note: Revealed type is 'Union[TypedDict('main.NewJobEvent', {'tag': Literal['new-job'], 'job_name': builtins.str, 'config_file_path': builtins.str}), TypedDict('main.CancelJobEvent', {'tag': Literal['cancel-job'], 'job_id': builtins.int}), TypedDict('main.AnotherOne', {'tag': Literal['another'], 'another': builtins.int})]'
main.py:32: note: Revealed type is 'Union[TypedDict('main.NewJobEvent', {'tag': Literal['new-job'], 'job_name': builtins.str, 'config_file_path': builtins.str}), TypedDict('main.CancelJobEvent', {'tag': Literal['cancel-job'], 'job_id': builtins.int}), TypedDict('main.AnotherOne', {'tag': Literal['another'], 'another': builtins.int})]'
  • What is the behavior/output you expect?
    I would expect the union of union to be narrowed

  • What are the versions of mypy and Python you are using?
    v0.782

  • Do you see the same issue after installing mypy from Git master?
    yes

  • What are the mypy flags you are using? (For example --strict-optional)

[mypy]
disallow_untyped_defs = True
ignore_missing_imports = True

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions