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

如何用Pydantic与Mypy正确标注typing.Annotated的返回类型?

环境

python 3.13
pydantic 2.10.5
mypy 1.16.0

问题描述

使用mypy作为类型检查器时,如何正确标注typing._SpecialForm(特指typing.Annotated)的返回类型?

代码示例

from functools import partial
from typing import Annotated

from pydantic import AfterValidator, BaseModel


def validate_smth(value: str, context: str) -> str:
    if value == "test":
        print(f"Validated {value}")
    else:
        raise ValueError(f"Value {value} is not allowed in context {context}")
    return value


def return_annotated_type(context: str = "") -> type: # error: 不兼容的返回值类型(得到"<typing special form>", 预期"type") [return-value]
    validator = partial(validate_smth, context=context)
    return Annotated[str, AfterValidator(validator)]


class MyModel(BaseModel):
    field: return_annotated_type(context="test") # error: 无效的类型注释或标注 [valid-type]
    # note: 建议:使用return_annotated_type[...]代替return_annotated_type(...)

MyModel.model_validate({"field": "test"})

尝试方案及问题

  • 标注返回类型为Annotated[str, AfterValidator]时,报错:error: 不兼容的返回值类型(得到"<typing special form>", 预期"str") [return-value]
    def return_annotated_type(context: str = "") -> Annotated[str, AfterValidator]:
    # error: 不兼容的返回值类型(得到"<typing special form>", 预期"str") [return-value]
    
  • 标注返回类型为Any时无报错,但类型范围过宽,不符合需求
    def return_annotated_type(context: str = "") -> Any:
    # 此处无报错,但Any范围太广,不符合需求
    

解决方案

方法1:使用TypeAlias标注返回类型

Python 3.10+和新版mypy支持用typing.TypeAlias标注返回值为类型别名,能让mypy正确识别Annotated返回的特殊类型:

from typing import Annotated, TypeAlias

def return_annotated_type(context: str = "") -> TypeAlias:
    validator = partial(validate_smth, context=context)
    return Annotated[str, AfterValidator(validator)]

方法2:用TypeAliasType精确定义(Python 3.12+)

Python 3.12引入了TypeAliasType,可以更清晰地定义动态生成的类型别名,同时消除mypy报错:

from typing import Annotated, TypeAliasType

def return_annotated_type(context: str = "") -> TypeAliasType:
    validator = partial(validate_smth, context=context)
    # 自定义类型别名名称,便于类型检查时识别
    return TypeAliasType(f"ValidatedStr_{context}", Annotated[str, AfterValidator(validator)])

方法3:提前赋值类型别名再使用

针对模型字段的valid-type报错,可以先将生成的类型赋值给变量,再在模型中引用:

# 提前生成类型别名
ValidatedTestStr = return_annotated_type(context="test")

class MyModel(BaseModel):
    field: ValidatedTestStr

这种方式能让mypy正确解析字段的类型标注。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 15:05:15