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

如何为attrs字段添加验证器并正确进行类型注解?

attrs中NewType字段添加验证器后的mypy类型错误解决

问题重现

当使用NewType定义自定义类型,并在attrs frozen类中为字段添加正则验证器时,mypy会抛出类型不兼容错误:

初始无验证器的代码(mypy无报错):

from typing import NewType
from attr import frozen, field

UserId = NewType("UserId", str)

@frozen
class Order:
    id: UserId = field()

添加验证器后的代码(mypy报错):

from typing import NewType
from attr import frozen, field, validators

UserId = NewType("UserId", str)

@frozen
class Order:
    id: UserId = field(validator=validators.matches_re("^\d+$"))

mypy报错信息:

project/test_annotation.py:10: error: Incompatible types in assignment
(expression has type "str", variable has type "UserId") [assignment]

Found 1 error in 1 file (checked 1 source file)

原因解释

这是因为:

  1. validators.matches_re的类型标注默认关联str类型,mypy会据此推断field()的返回类型为str,而字段注解是基于str的自定义UserId(NewType),mypy不会自动将原始类型str转换为NewType子类。
  2. 在attrs 22.x版本中,当给field()指定验证器时,类型推断逻辑会优先匹配验证器的输入类型,而非字段的注解类型,最终导致类型不匹配。

解决办法

这里提供几种可行的方案:

方案1:给field指定明确的type参数

直接在field()中通过type参数声明字段类型为UserId,让mypy正确识别:

from typing import NewType
from attr import frozen, field, validators

UserId = NewType("UserId", str)

@frozen
class Order:
    id: UserId = field(validator=validators.matches_re("^\d+$"), type=UserId)

方案2:添加转换器自动转换类型

使用converter参数将输入的str自动转换为UserId类型,同时保留验证逻辑,运行时和静态检查都能正常工作:

from typing import NewType
from attr import frozen, field, validators

UserId = NewType("UserId", str)

@frozen
class Order:
    id: UserId = field(
        validator=validators.matches_re("^\d+$"),
        converter=UserId
    )

这个方案的优势是实例化Order时可以直接传入符合格式的字符串,无需手动用UserId()包裹。

方案3:使用cast强制类型转换

如果不想修改field参数,可以用typing.cast告诉mypy字段的实际类型:

from typing import NewType, cast
from attr import frozen, field, validators

UserId = NewType("UserId", str)

@frozen
class Order:
    id: UserId = cast(UserId, field(validator=validators.matches_re("^\d+$")))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 09:05:32