Search code examples
pythontypesmypy

Asking isinstance on a Union[...] type


I'm trying to ask an isinstance question on a user defined type: ConstData = Union[int, str]:

from typing import Union, Optional
ConstData = Union[int, str]
def foo(x) -> Optional[ConstData]:
    if isinstance(x, ConstData):  # <--- this doesn't work
    # if isinstance(x, (int, str)): <--- this DOES work ...
        return x
    return None

Sadly enough, it doesn't work:

$ mypy main.py
main.py:4: error: Parameterized generics cannot be used with class or instance checks
main.py:4: error: Argument 2 to "isinstance" has incompatible type "object"; expected "Union[type, Tuple[Union[type, Tuple[Any, ...]], ...]]"
Found 2 errors in 1 file (checked 1 source file)

Is there any elegant way to solve this?


Solution

  • About:

    "Still, with if isinstance(x, get_args(ConstData)): return x mypy can't infer that x has the correct return type. It complains it's Any"

    I think it is a bug in reveal_type(), Mypy undertands the narrowing of x type. As you can see in the following code, it does not raise an error when test() is called with x:

    def test(k:Union[int, str]) -> None:
        pass
    
    
    def foo(x: Any) -> Optional[ConstData]:
        if isinstance(x, get_args(ConstData)):
            reveal_type(x)  # Mypy: Revealed type is "Any"
            test(x)  # Mypy: no error
            return x  # Mypy: no error
        return None