我正在尝试为 API 客户端定义两个版本的类型化字典,一个
total=False
用于部分更新路由输入,另一个 total=True
用于响应。任何具有字段子集的字典都可以作为输入有效,但输出字典必须包含所有字段。
我试过这个:
class PartialDict(TypedDict, total=False):
name: str
age: int
class FullDict(PartialDict, total=True):
pass
但它不起作用,因为 Mypy 1.13 不会抱怨以下任何一个:
x: PartialDict = {} # ok
y: FullDict = {} # should fail
如果我反转继承并使
PartialDict
继承定义字段的 FullDict
,Mypy 会抱怨这两行:
mymodule/types.py:38: error: Missing keys ("name", "age") for TypedDict "PartialDict" [typeddict-item]
mymodule/types.py:39: error: Missing keys ("name", "age") for TypedDict "FullDict" [typeddict-item]
如何定义类型,例如
FullDict
必须具有所有键,但 PartialDict
可能不具有所有键?我想避免重复课程,因为我的现实世界字典有几十个键。
正如此评论中所述,您无法完全按照您的要求去做。
total
既不继承自 TypedDict
子类,也不追溯应用于其超类中的项目。
但是,如果我们回到这个问题,
任何具有字段子集的字典都可以作为输入有效,但输出字典必须包含所有字段。
这个是可以模仿的。这个想法是,输入在被修改时处于
total=False
状态,而输出仍然是非 total
,但与防止删除任何项目的类型联合。演示(mypy Playground、Pyright Playground):
import typing as t
import collections.abc as cx
type FullDict[T: BaseTypedDict] = T | cx.Mapping[t.Any, t.Any]
class BaseTypedDict(t.TypedDict):
pass
class PartialDict(t.TypedDict, total=False):
name: str
age: int
def populate(td: PartialDict, /) -> FullDict[PartialDict]:
td["age"] = 20
return td
>>> x: PartialDict = {"name": "John"}
>>> y: FullDict[PartialDict] = populate(x)
>>>
>>> del y["age"] # Error: no method "__delitem__"
>>> y.pop("name") # Error: no method "pop"