(请注意,这在sorbet.run上是不可复制的,据我所知,它只能在本地的Sorbet上复制)
我希望我可以使用Typed Structs feature创建一个方法签名,其中一个参数是一个options
哈希,但这是行不通的:
# typed: true
require 'sorbet-runtime'
extend T::Sig
class OptionsStruct < T::Struct
prop :x, Integer, default: 1
end
sig { params(options: OptionsStruct).void }
def method(options)
puts options.x
end
# This works
method(OptionsStruct.new({x: 2}))
# This causes the typechecker to throw.
method({x: 2})
本质上,当您对该文件进行类型检查时,它会抱怨在需要Struct时传递哈希值。我的问题是:如何为具有特定参数的哈希定义有效签名?结构显然在这里不起作用。虽然我还没有尝试过Shapes,但是根据文档,它们非常有限,所以我宁愿不要使用它们。
documentation on generics提到了哈希,但是似乎建议仅在哈希的键和值都是相同类型的情况下才可以使用它们(例如,Hash<Symbol, String>
要求所有键都是Symbols,所有值都是Strings) ),并且(据我所知)没有提供任何方法来定义具有特定键的哈希。
谢谢!
答案 0 :(得分:2)
基本上,您必须选择采用多种方式之一(您已经提到了三种):
T::Hash[KeyType, ValueType]
。这样,您可以在调用将其作为参数的方法时使用{}
语法,但会强制您为每个条目使用相同类型的键和值。T::Hash[KeyType, Object]
。在值的类型上这有点灵活...但是您会丢失类型信息。T::Hash[KeyType, T.any(Type1, Type2, ...)
。这是介于1和2之间的中间位置。T::Struct
的最好方法:sig { params(options: {x: Integer}).void }
def method(options)
puts options[:x]
end
T::Struct
。这迫使您使用MyStruct.new(prop1: x, prop2: y, ...)
所有这些参数都是有效的,其中4和5是为您提供最大类型安全性的参数。在这两个参数中,呼叫者最灵活的是4个,但是您知道Sorbet
在短期/中期不会改变支持的那个是5个。