Skip to content

Type narrowing tagged union consisting of classes by its tag using match does not work #6752

Closed

Description

Describe the bug
See also: python/mypy#16286
Narrowing a type of a tagged union that consists of classes does not work with match statement, but does work with ifs.

Code or Screenshots

from typing import Literal

class A:
    tag: Literal["a"]
    name: str

class B:
    tag: Literal["b"]
    num: int

def f(d: A | B) -> None:
    if d.tag == "a":
        reveal_type(d)  # Type of "d" is "A"
    elif d.tag == "b":
        reveal_type(d)  # Type of "d" is "B"

def g(d: A | B) -> None:
    match d.tag:
        case "a":
            reveal_type(d)  # Type of "d" is "A | B"
        case "b":
            reveal_type(d)  # Type of "d" is "A | B"

(example taken from python/mypy#16286 (comment).)

VS Code extension or command-line

$ pyright --version
pyright 1.1.341
Little off-topic

Unlike mypy, pyright does correctly handle the TypedDict version:

from typing import Literal, TypedDict

class A(TypedDict):
    tag: Literal["a"]
    name: str
    
class B(TypedDict):
    tag: Literal["b"]
    num: int

def f(d: A | B) -> None:
    if d["tag"] == "a":
        reveal_type(d)  # Type of "d" is "A"
    elif d["tag"] == "b":
        reveal_type(d)  # Type of "d" is "B"

def g(d: A | B) -> None:
    match d["tag"]:
        case "a":
            reveal_type(d)  # Type of "d" is "A"
        case "b":
            reveal_type(d)  # Type of "d" is "B"

(example taken from python/mypy#16286 (comment).)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions