父类TypedDict为何无法赋值给含NotRequired字段的子类TypedDict?
问题原因
尽管Child的child_field标记为NotRequired,但类型检查器(pyright/mypy)对TypedDict的子类型兼容性有严格要求:Child作为Parent的子类,其类型定义隐含了“对象可以包含child_field”的约束,而Parent类型的实例完全不包含该字段的定义(既没有键,也没有默认值),因此无法直接赋值给Child类型的变量。TypedDict的结构类型检查不会自动将父类型实例视为兼容子类型,哪怕子类型的字段是可选的。
解决方案
这里提供几种实用的规避方式,可根据场景选择:
方式一:字典展开生成兼容实例
通过字典展开创建新对象,类型检查器会自动识别新对象符合Child的结构要求(包含必填的parent_field,且允许缺少可选的child_field):
from typing_extensions import NotRequired, TypedDict class Parent(TypedDict): parent_field: str class Child(Parent): child_field: NotRequired[bool | None] def create_parent() -> Parent: return {"parent_field": "example"} # 字典展开生成符合Child类型的实例 child: Child = {**create_parent()}
方式二:类型断言(Cast)
如果需要直接复用create_parent()的返回值,可使用类型断言明确告诉类型检查器该值可以被当作Child类型,适合简单场景:
from typing_extensions import NotRequired, TypedDict, cast # (Parent、Child、create_parent定义同上) child: Child = cast(Child, create_parent())
方式三:泛型函数复用生成逻辑
如果需要支持多个不同的子类TypedDict,用泛型函数封装基础字典生成逻辑,同时返回目标类型:
from typing_extensions import NotRequired, TypedDict from typing import TypeVar # 定义绑定到Parent的类型变量 T = TypeVar('T', bound='Parent') class Parent(TypedDict): parent_field: str class Child(Parent): child_field: NotRequired[bool | None] class AnotherChild(Parent): another_field: NotRequired[int] def create_base_dict() -> Parent: return {"parent_field": "example"} def create_typed_dict(target_type: type[T]) -> T: base_dict = create_base_dict() # 可根据需要为子类字段添加默认值 # if target_type is Child: # base_dict["child_field"] = None return base_dict # 生成不同子类的实例 child: Child = create_typed_dict(Child) another_child: AnotherChild = create_typed_dict(AnotherChild)
内容的提问来源于stack exchange,提问作者Matija Sirk
相关产品推荐
相关产品推荐

