Sorbet不允许Zlib::GzipReader作为方法参数的问题排查
解决Sorbet中Zlib::GzipReader类型签名错误
问题场景
定义包含Zlib::GzipReader类型参数的方法签名时,触发Sorbet错误:
Malformed type declaration. Generic class without type arguments Zlib::GzipReader
尝试将签名改为Zlib::GzipReader[T.anything]后,又出现新错误:
Method [] does not exist on T.class_of(Zlib::GzipReader)[Zlib::GzipReader[T.anything]]
相关代码示例:
sig { params(source: T.any(String, Zlib::GzipReader)).returns(T::Boolean) } def file?(source) source.is_a?(String) && File.exist?(source.to_s) end
问题原因
Sorbet的标准库rbi文件将Zlib::GzipReader定义为泛型类(协变泛型,类型参数约束为IO子类),因此必须指定类型参数才能合法使用;而T.anything并非Sorbet认可的合法类型参数写法,导致第二个错误。
解决方案
根据需求选择以下任意一种写法:
1. 使用IO基类作为类型参数(推荐)
由于Zlib::GzipReader的泛型参数约束为IO子类,用IO作为类型参数可以覆盖所有合法的GzipReader实例:
sig { params(source: T.any(String, Zlib::GzipReader[IO])).returns(T::Boolean) } def file?(source) source.is_a?(String) && File.exist?(source.to_s) end
2. 使用T.untyped忽略内部类型
如果不需要检查Zlib::GzipReader包装的具体IO类型,可使用T.untyped作为泛型参数:
sig { params(source: T.any(String, Zlib::GzipReader[T.untyped])).returns(T::Boolean) } def file?(source) source.is_a?(String) && File.exist?(source.to_s) end
3. 临时用T.untyped绕过检查(不推荐)
若仅需快速通过类型检查,可将Zlib::GzipReader替换为T.untyped,但会失去类型校验能力:
sig { params(source: T.any(String, T.untyped)).returns(T::Boolean) } def file?(source) source.is_a?(String) && File.exist?(source.to_s) end
内容的提问来源于stack exchange,提问作者Richard Nienaber
相关产品推荐
相关产品推荐

