联合中 io.TextIOBase 的类型检查问题

Type-checking issue with io.TextIOBase in a Union

在下面的代码中,我有一个函数可以接受字符串或一些 TextIOBase。如果传递了一个字符串,它被解释为应该打开和读取的文件的路径。如果传递 TextIOBase,将读取该流的内容:

from typing import Union
import io

def function(foo: Union[str, io.TextIOBase]) -> None:
    if isinstance(foo, str):
        foo = open(foo, "w")

这看起来应该没问题,因为联合应该是协变的,这意味着联合中的一种类型的子类应该满足类型注释,在这种情况下 [=15 的输出类型=] 是 TextIOBase 的子类。然而,mypy 抱怨:

union.py:6: error: Incompatible types in assignment (expression has type "TextIO", variable has type "Union[str, TextIOBase]")
Found 1 error in 1 file (checked 1 source file)

我认为根据传递的参数,open() 的 return 类型可能存在歧义问题,因此我尝试改为 StringIO,但得到了同样的错误。有什么想法吗?为什么 mypy 生我的气?

我也用一些玩具类试过这个(例如Union[str, T1],然后分配一个T2,其中T2是T1的子类),mypy非常满意。

typing 模块有一个专用对象:typing.TextIOopen 的 return 类型根据 mode 参数确定,并评估为以下类型之一:TextIOBinaryIO.