You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MyPy检查简单Union类型时出现类型不兼容错误

MyPy类型检查失败原因及解决办法

这不是MyPy的bug,而是由字典类型的不变性和Union类型的匹配规则共同导致的,具体细节如下:

  • 字典类型的不变性:Python的Dict是可变容器,在类型系统中属于不变类型。也就是说,哪怕V1是V2的子类型,Dict[K, V1]也不能被当作Dict[K, V2]使用。你的A类型是Dict[str, Union[str, Dict[str, str]]],而{"x": {"y": "z"}}的推断类型是Dict[str, Dict[str, str]],两者的值类型(一个是Union,一个是单一字典类型)不相等,所以严格意义上不兼容。

  • 直接标注A时的特殊处理:当你把这个字典直接赋值给标注为A的变量时,MyPy会对字典字面量做隐式类型拓宽——它会自动将字面量的类型调整为A,因为每个值都符合Union[str, Dict[str, str]]的要求。这是MyPy为了提升易用性做的特殊优化。

  • Union类型的严格匹配:当目标类型是Union[A, Dict[str, str]]时,MyPy会严格检查表达式类型是否兼容Union中的任意一个成员。此时表达式的类型Dict[str, Dict[str, str]]既不严格兼容A(受限于Dict的不变性),也不兼容Dict[str, str],因此触发报错。

解决办法

方法一:显式类型转换

通过cast告诉MyPy该字典的实际类型,或者用# type: ignore跳过检查:

from typing import Dict, Union, cast

A = Dict[str, Union[str, Dict[str, str]]]
B = Union[A, Dict[str, str]]

# 使用cast明确类型
example: B = cast(A, {"x": {"y": "z"}})

# 跳过检查(不推荐,仅在确认类型安全时使用)
example: B = {"x": {"y": "z"}}  # type: ignore

方法二:改用协变的Mapping类型

如果不需要修改这个字典,可以用Mapping替代Dict。Mapping是协变类型,允许值类型的子类型兼容:

from typing import Mapping, Union

A = Mapping[str, Union[str, Mapping[str, str]]]
B = Union[A, Mapping[str, str]]

example: B = {"x": {"y": "z"}}  # MyPy检查通过

内容的提问来源于stack exchange,提问作者levand

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 12:14:58