如何让MyPy将TypedDict识别为兼容的dict类型?
问题描述
我定义了以下TypedDict类:
from typing import TypedDict, Any class Appinfo(TypedDict): appid: int extended: dict[str, Any] config: dict[str, Any] depots: dict[str, Any] ufs: dict[str, Any] class SteamAppInfo(TypedDict): appid: int data: dict[str, Appinfo]
随后将SteamAppInfo类型的变量传入一个期望接收dict的函数:
from functools import reduce import operator def dict_get_key_list(data: dict[str, Any], key_list: list[str]) -> Any: """根据提供的嵌套字典键列表返回字典值或None""" try: return reduce(operator.getitem, key_list, data) except KeyError: return None
代码运行正常(SteamAppInfo本质就是字典),但MyPy抛出类型错误:
error: Argument 1 to "dict_get_key_list" of "Utils" has incompatible type "SteamAppInfo"; expected "Dict[str, Any]"
请问如何让MyPy识别传入的是字典类型,无需枚举所有TypedDict或设置变量类型为Any?
解决方法
有三种简洁的方案可以解决该类型兼容问题:
1. 让TypedDict显式继承dict[str, Any]
修改SteamAppInfo的定义,让它直接继承dict[str, Any],MyPy会自动识别其为字典子类:
class SteamAppInfo(TypedDict, dict[str, Any]): appid: int data: dict[str, Appinfo]
2. 使用typing.cast临时转换类型
在调用函数时,用cast将SteamAppInfo变量转换为dict[str, Any],明确告知MyPy该变量符合参数类型要求:
from typing import cast steam_app_info: SteamAppInfo = {"appid": 123, "data": {}} result = dict_get_key_list(cast(dict[str, Any], steam_app_info), ["data", "some_key"])
3. 泛化函数的参数类型(推荐)
修改dict_get_key_list的参数类型,让它接受所有Mapping类型(TypedDict属于Mapping的子类),既保留类型检查能力,又支持更多键值对容器类型:
from typing import Mapping, Any from functools import reduce import operator def dict_get_key_list(data: Mapping[str, Any], key_list: list[str]) -> Any: """根据提供的嵌套字典键列表返回字典值或None""" try: return reduce(operator.getitem, key_list, data) except KeyError: return None
内容的提问来源于stack exchange,提问作者rkr87
相关产品推荐
相关产品推荐

