MyPy 不允许将 TypedDict 的 class 作为参数传递给函数

MyPy does not allow passing class of the TypedDict as an argument to a function

以下代码:

class A(TypedDict):
    abc: str


class B(TypedDict):
    xyz: str


def func(dict_class: Union[type[A], type[B]]) -> None:
    print(dict_class.__annotations__)


func(A)

导致以下 MyPy 错误:

error: Argument 1 to "func" has incompatible type "Type[A]"; expected "Union[Type[A], Type[B]]"

是否有任何其他方式告诉 MyPy dict_class 参数只能是指定类型的字典类型?我知道我可以将类型提示更改为更通用的内容,这样 MyPy 就不会抱怨,但我真的不想这样做。

更重要的是 PyCharm IDE 似乎适用于此示例。那么它是 MyPy 错误吗?

这是使用 TypedDict 时的一个已知问题,例如 here

更简单的例子:

from typing import TypedDict

D = TypedDict('D', {})
x: type[D] = D  # error

产生不明显的消息:

error: Incompatible types in assignment (expression has type "Type[D]", variable has type "Type[D]")

@ilevkivskyi 这样解释这种行为 here

Yeah, this doesn't work because Type[...] is not supposed to work with anything but classes, unions of classes, and Any, see PEP 484.

It seems to me it might be possible to relax this limitation to some extent, but first of all we should fix the errors message, which is cryptic.

您可以在 PEP 589. @serhiy.storchaka briefly described it here 中阅读有关使用 TypedDict 的更多信息,如下所示:

TypeDict is a callable, it can be used as

Point2D = TypedDict('Point2D', x=int, y=int, label=str)

It can also be used as a base in class definition, but is is not a class itself. It does not occur in __bases__ of the created class, and it cannot be used in isinstance() and issubclass() checks. It is just yet one weird way to customize class creation.