Pyright中自定义类的Callable联合类型别名未按预期报错
问题分析与解答
结论
这是Pyright当前版本的设计限制,而非bug,也无需额外操作来适配自定义类。
具体原因
单独Callable类型的检查逻辑
当直接使用Callable[[C, C], C]时,Pyright会同时校验两点:- 函数签名是否匹配(lambda接受两个
C类型参数,符合要求) - 函数体内的类型合法性:由于
C没有定义__add__方法,a + b的返回类型为Any,无法满足C类型的返回值要求,因此触发报错。
- 函数签名是否匹配(lambda接受两个
联合类型Callable的检查逻辑
当使用联合类型别名F[C, C](即Callable[[C], C] | Callable[[C, C], C])时,Pyright的检查逻辑会宽松化:只要目标lambda能匹配联合中的任意一个分支签名,就会跳过对该分支的深度类型校验,或降低错误检查优先级。
这里lambda的签名(两个参数)本应匹配Callable[[C, C], C]分支,但Pyright在联合类型场景下,没有触发对该分支函数体内a + b的类型错误检查。内置类型set的特殊情况
对于set这类内置类型,Pyright内置了严格的语义规则:明确知道set不支持+运算符,因此无论是否在联合类型中,a + b都会被直接判定为错误,不受联合类型检查逻辑的影响。
临时解决方案
如果需要严格的类型校验,建议避免使用联合类型的Callable别名,而是单独标注具体的Callable类型;或者使用Protocol定义可调用接口,能获得更精准的类型检查效果。
内容的提问来源于stack exchange,提问作者weiss_i_net
相关产品推荐
相关产品推荐

