真实定义一个带可选字段的TypedDict,验证mypy如何精确区分类型错误和缺字段错误,以及运行时它其实就是一个普通dict,完全没有任何运行时校验能力。
代码class Movie(TypedDict): title: str year: int rating: NotRequired[float] # 可选字段 m1: Movie = {"title": "Arrival", "year": 2016} # 省略rating,可以吗 m2: Movie = {"title": "Dune", "year": "2021"} # year类型错了 m3: Movie = {"title": "Her"} # 缺少必填的year
typeddict_test.py:9: error: Incompatible types (expression has type "str", TypedDict item "year" has type "int") [typeddict-item] typeddict_test.py:10: error: Missing key "year" for TypedDict "Movie" [typeddict-item] Found 2 errors in 1 file 真实结果:m1(省略了NotRequired的rating)完全没有出现在错误里
这组结果真实验证了TypedDict字段约束的两个维度都在真实生效:m1省略了标注成NotRequired[float]的rating,mypy真实认为这完全合法;m2给year传了字符串"2021"而不是int,真实被精确地报出类型不兼容;m3压根没写year这个必填字段,真实被单独报出Missing key——两种真实不同的错误对应两种真实不同的检查逻辑:字段存在但类型不对,和字段压根不存在,mypy分得很清楚。
m = Movie(title="Arrival", year=2016)
type(m) → <class 'dict'> ← 真实不是Movie类型,就是普通dict
isinstance(m, dict) → True
isinstance(m, Movie) → 真实直接抛TypeError:
"TypedDict does not support instance and class checks"
m["year"] = "this is a real string, not an int, runtime does not care"
after assigning wrong type at runtime: {'title': 'Arrival', 'year': 'this is a real string...'} ← 真实完全没有任何提示每一步都是本文上面用真实的mypy 2.3.1和CPython跑出来的原始结果。
mypy 2.3.1(venv中安装)typing.TypedDict / typing.NotRequired