Ruby冰糕哈希类型检查



我想知道为什么Sorbet没有抱怨这个例子:示例:

sig {params(x: T::Hash[String, String]).void}
def foo(x)
x.each do |k, v|
puts "key = #{k}, value = #{v}"
end
end
hash = {}
hash[1] = 1
foo(hash) #  I'd expect this to fail to type-check

我已经声明foo接受[String, String]的哈希值,但我正在传递[Integer, Integer]的哈希值。我以为雪葩会抱怨…

是否有一种方法可以使这种情况出错?

问题是hash不是T::Hash[Integer, Integer]型,而是T::Hash[T.untyped, T.untyped]型。你可以使用T.reveal_type:

hash = {}
hash[1] = 1
T.reveal_type(hash) # Revealed type: {} (shape of T::Hash[T.untyped, T.untyped])

发生这种情况是因为Sorbet在创建时没有关于您的哈希的信息。解决方案是显式初始化它:

hash = T::Hash[Integer, Integer].new
hash[1] = 1
foo(hash) # Expected T::Hash[String, String] but found T::Hash[Integer, Integer] for argument x

你可以在这里看到完整的代码

根本原因是hash最初被解释为Shape(参见https://sorbet.org/docs/shapes),没有任何类型信息。

最新更新