我想知道为什么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),没有任何类型信息。