为Ruby Gem添加RBS时,如何处理可选Block的类型校验问题
解决RBS可选Block的类型校验问题
问题场景
现有Ruby方法:
def some_method(&block) if block foo = block.call end end
对应的RBS签名:
def some_method: () ?{ () -> String } -> void
执行steep check时触发错误:
[error] Type
nildoes not have methodcall
│ Diagnostic ID: Ruby::NoMethod
│
└ foo = block.call
~~~~
需要保留&block为可选参数,且不修改原有代码逻辑,解决类型校验错误。
解决方案
方案1:添加Steep类型断言注释
在if block分支内添加类型注释,明确告知Steep该分支中block不为nil,无需修改业务逻辑代码:
def some_method(&block) if block # @type var block: () -> String foo = block.call end end
Steep会识别该注释,在分支内将block的类型细化为非nil的Proc类型,消除错误。
方案2:使用RBS重载签名
将原RBS签名拆分为两个重载,分别对应“不带block”和“带block”的场景:
def some_method: () -> void def some_method: () { () -> String } -> void
这种写法会让Steep根据调用时是否传入block匹配对应的签名,if block分支只会在带block的签名下触发,自然不会出现nil调用call的错误。
内容的提问来源于stack exchange,提问作者Paul W
相关产品推荐
相关产品推荐

