在 Union[...] 类型上询问 isinstance

Asking isinstance on a Union[...] type

我想问一个关于用户定义类型的 isinstance 问题: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

遗憾的是,它不起作用:

$ 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)

有什么优雅的方法可以解决这个问题吗?

关于:

“仍然,if isinstance(x, get_args(ConstData)): return x mypy 无法推断出 x 具有正确的 return 类型。它抱怨它是 Any

我认为这是 reveal_type() 中的一个错误,Mypy 理解 x 类型的缩小。正如您在以下代码中看到的,当使用 x 调用 test() 时它不会引发错误:

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