首页 > 解决方案 > Ruby Sorbet 哈希类型检查

问题描述

我想了解为什么 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] 的哈希值。我以为冰糕会在这里抱怨...

有没有办法让它在这种情况下出错?

标签: rubysorbet

解决方案


问题是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最初被解释为 a Shape(参见https://sorbet.org/docs/shapes),没有任何类型信息。


推荐阅读