使用mypy时函数类型注解报错:Invalid type comment or annotation [valid-type]
问题描述
mypy抛出类型错误:
error: Invalid type comment or annotation [valid-type]
相关代码如下:
动态分页模型生成类
class PaginatedResults: def __new__(cls, model_to_paginate): fields = { "data": (typing.List[model_to_paginate], []), "limit": (int, DEFAULT_PAGE_SIZE), "offset": (int, 0), "total": (int, 0), } return create_model(f"Paginated{model_to_paginate.__name__}", **fields)
Pydantic模型定义
class Car(BaseModel): id: int
函数使用代码
def my_function(limit: int, offset:int) -> PaginatedResults(Car) total=0 return PaginatedResults(Car)( data=[], limit=limit, offset=offset, total=0, )
代码能正常运行,但mypy持续报错,求正确处理方式。
解决方案
mypy报错的核心原因是:PaginatedResults(Car)是运行时调用表达式,无法直接作为静态类型注解使用——mypy在静态检查阶段无法解析动态生成的类型,需要通过以下方式处理:
1. 改用泛型类(推荐方案)
将PaginatedResults重构为泛型类,让mypy能识别类型参数,同时保留分页模型的复用性:
from typing import Generic, TypeVar, List from pydantic import BaseModel T = TypeVar('T') DEFAULT_PAGE_SIZE = 10 class PaginatedResults(BaseModel, Generic[T]): data: List[T] = [] limit: int = DEFAULT_PAGE_SIZE offset: int = 0 total: int = 0 # 函数注解直接使用泛型类型 def my_function(limit: int, offset: int) -> PaginatedResults[Car]: return PaginatedResults[Car]( data=[], limit=limit, offset=offset, total=0, )
这种方案既保证了类型安全,又让mypy能正确校验返回值类型,同时避免了动态生成类的复杂性。
2. 用cast兼容动态生成场景(适合必须保留原逻辑的情况)
如果因业务需求必须保留动态生成类的逻辑,可以通过cast显式告知mypy实际返回类型:
from typing import cast, TypeVar from pydantic import BaseModel, create_model T = TypeVar('T') DEFAULT_PAGE_SIZE = 10 class PaginatedResults: def __new__(cls, model_to_paginate: type[T]) -> type[BaseModel]: fields = { "data": (list[model_to_paginate], []), "limit": (int, DEFAULT_PAGE_SIZE), "offset": (int, 0), "total": (int, 0), } return create_model(f"Paginated{model_to_paginate.__name__}", **fields) class Car(BaseModel): id: int def my_function(limit: int, offset: int): return cast(PaginatedResults(Car), PaginatedResults(Car)( data=[], limit=limit, offset=offset, total=0, ))
3. 临时忽略mypy错误(不推荐)
如果只是临时绕过检查,可以在报错行添加注释忽略特定错误:
def my_function(limit: int, offset:int) -> PaginatedResults(Car): # type: ignore[valid-type] total=0 return PaginatedResults(Car)( data=[], limit=limit, offset=offset, total=0, )
这种方式会跳过该行的类型检查,丢失mypy的静态类型保障,不建议长期使用。
内容的提问来源于stack exchange,提问作者Johnne
相关产品推荐
相关产品推荐

