Skip to content

Type narrowing fails when narrowing Optional NewTypeΒ #11995

Closed
@bbatliner

Description

@bbatliner

Bug Report

from typing import Union, NewType

Int = NewType("Int", int)
Float = NewType("Float", float)

def raw_types(arg: Union[int, float, None]) -> None:
    if isinstance(arg, int):
        reveal_type(arg)  # Revealed type is "builtins.int"
    elif isinstance(arg, float):
        reveal_type(arg)  # Revealed type is "builtins.float"
    else:
        reveal_type(arg)  # Revealed type is "None"

def new_types(arg: Union[Int, Float, None]) -> None:
    if isinstance(arg, int):
        reveal_type(arg)  # Revealed type is "__main__.Int"
    elif isinstance(arg, float):
        reveal_type(arg)  # Revealed type is "Union[__main__.Int, __main__.Float]" (NARROWING FAILED)
    else:
        reveal_type(arg)  # Revealed type is "None"

def new_types_not_optional(arg: Union[Int, Float]) -> None:
    if isinstance(arg, int):
        reveal_type(arg)  # Revealed type is "__main__.Int"
    elif isinstance(arg, float):
        reveal_type(arg)  # Revealed type is "__main__.Float"
    else:
        reveal_type(arg)

The bug is fairly straightforward. When narrowing a Union of NewType types with isinstance, the narrowing fails if one of the possible types of the variable is None.

To Reproduce

https://mypy-play.net/?mypy=0.931&python=3.10&gist=557b54a098f8ed366fa62ff380ec12c8

Expected Behavior

All revealed types after isinstance(arg, float) would be builtins.float or __main__.Float.

Actual Behavior

The revealed type in the buggy case is still Union[__main__.Int, __main__.Float].

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-type-narrowingConditional type narrowing / binder

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions