声明式HTTP客户端依赖注入的mypy类型提示问题
解决mypy类型不匹配错误的方案
要解决你遇到的默认值类型不匹配问题,同时保留类似FastAPI的声明方式,可通过泛型+工厂函数+类型转换的组合实现类型提示兼容:
步骤1:重构Dependency为泛型基类
首先将Dependency改为泛型类,关联目标类型T,让子类能绑定到参数注解的类型:
from typing import TypeVar, Generic, Any, Optional import abc T = TypeVar("T") Empty = object() # 假设你的Empty是类似的特殊标识值 class Dependency(Generic[T], abc.ABC): def __init__( self, default: Any = Empty, field_name: Optional[str] = None, ): self.default = default self._overridden_field_name = field_name @abc.abstractmethod def modify_request(self, request: "RawRequest") -> "RawRequest": raise NotImplementedError
步骤2:将Json改为内部实现类
把原来的Json类改为内部实现类_JsonImpl,继承泛型Dependency[T],保留原有功能逻辑:
class _JsonImpl(Dependency[T]): location = Location.json def __init__(self, default: Any = Empty): super().__init__(default=default) def modify_request(self, request: "RawRequest") -> "RawRequest": # 保留你的请求修改逻辑 return request
步骤3:编写工厂函数Json
创建一个工厂函数Json,利用typing.cast让mypy将返回值推断为参数注解的类型,同时实际返回_JsonImpl实例:
from typing import cast def Json(default: Any = Empty) -> T: """声明JSON类型的请求参数,兼容dict、Pydantic模型、dataclass等任意类型""" return cast(T, _JsonImpl(default))
用法保持不变
现在你依然可以用原来的方式声明函数,mypy会自动推断Json()的类型为参数注解的类型,不会再报错:
@http("GET", "/example") def test_get(data: dict = Json()): ... # 支持Pydantic模型示例 from pydantic import BaseModel class User(BaseModel): name: str age: int @http("POST", "/user") def create_user(user: User = Json()): ...
原理说明
- 泛型
Dependency[T]让内部实现类绑定到参数注解的目标类型 - 工厂函数
Json通过cast(T)让mypy认为返回值是注解的类型,而实际运行时返回的是具备请求修改逻辑的_JsonImpl实例 - 装饰器
@http依然可以正常识别Dependency实例并执行modify_request逻辑,功能不受影响
内容的提问来源于stack exchange,提问作者floydya
相关产品推荐
相关产品推荐

