在仅用RBI文件存储类型信息的Ruby gem中如何处理Sorbet报错
关于仅用RBI存储类型信息的合理性
你的做法完全没有问题。Sorbet原生支持将所有类型声明统一存放在顶层rbi/目录下的*.rbi文件中,不需要在业务源码里引入任何Sorbet相关的语法或依赖,下游用户如果不使用Sorbet,完全感知不到这些类型文件的存在,不会给他们带来任何额外负担,完全匹配你的需求。
保留运行时校验且避免Sorbet报错的方案
不需要全局禁用7006错误,也不需要删除运行时校验,有两种低成本方案可选:
- 单行错误忽略:直接在触发报错的代码行末尾添加Sorbet专属忽略注释即可,仅屏蔽当前行的7006错误,不会影响其他代码的检查,是最符合你需求的方案:
这个方案不需要修改任何业务逻辑,添加的注释对运行时没有任何影响,也不需要引入Sorbet运行时依赖。def initialize(runs, mediabox) raise ArgumentError, "a mediabox must be provided" if mediabox.nil? # srb: ignore 7006 end - 用
T.unsafe包裹校验对象:如果不介意在源码里出现极少量Sorbet相关代码,可以将校验的对象用T.unsafe包裹,让Sorbet跳过对该对象的类型推导,就不会判定条件永远为假:
如果担心def initialize(runs, mediabox) raise ArgumentError, "a mediabox must be provided" if T.unsafe(mediabox).nil? endT不存在导致运行时报错,可以提前在gem的入口文件里加个fallback定义,不需要完整引入sorbet-runtime:# 放在gem入口最顶部,仅当没有加载sorbet-runtime时生效 unless defined?(T) T = Module.new do def self.unsafe(obj) obj end end end
关于是否要移除运行时校验
Sorbet官方从来没有要求公共库移除运行时校验,反而非常鼓励公共库保留必要的运行时参数校验:Sorbet的静态检查仅能覆盖使用了Sorbet的下游用户,对于没有启用Sorbet的下游用户,静态类型约束完全不生效,运行时校验是保障gem鲁棒性的必要手段,完全不需要移除。
内容的提问来源于stack exchange,提问作者James Healy
相关产品推荐
相关产品推荐

