如何在运行时在 sorbet 中的 `T::Struct` 上动态定义 `prop`?
How to dynamically define `prop`s on a `T::Struct` in sorbet at runtime?
我有一个结构定义为:
# typed: true
require 'sorbet-runtime'
class MyStruct < T::Struct
MyPropType = T.type_alias { T::Hash[Symbol, Class] }
class << self
extend T::Sig
sig { params(props: MyPropType).void }
def register_props(props)
props.each do |prop_name, prop_type|
prop(prop_name, prop_type)
end
end
end
end
注意 prop
是如何在运行时定义的。
然后在我的代码库的某个地方,在启动时,我做 MyStruct.register_props({ foo: T.untyped, bar: T.nilable(T.untyped) })
。
初始化 MyStruct
在通过类型检查传递代码库时出错。 MyStruct.new(foo: 'foo', bar: Bar.new)
.
$ ./bin/srb typecheck
/path/to/file.rb:66: Too many arguments provided for method MyStruct#initialize. Expected: 0, got: 1 https://srb.help/7004
如何在运行时在 T::Struct
上定义 prop
s 而不会出现上述类型检查错误?
AFAIK T::Struct
s 不能动态定义(我的意思是他们可以但是......),因为类型检查器需要静态地知道它将拥有哪些道具。对于这种情况,我认为您应该使用 T::InexactStruct
。参见 https://github.com/sorbet/sorbet/blob/master/gems/sorbet-runtime/lib/types/struct.rb
编辑:添加片段以供将来参考
# typed: strict
class SomeStruct < T::InexactStruct
extend T::Sig
sig { params(props: T::Array[T.untyped]).void }
def self.register(props)
props.each do |name, type|
prop name, type
end
end
end
SomeStruct.register [[:one, String], [:two, String]]
SomeStruct.new() # This would raise an error on runtime because of missing arguments, but not on static check
SomeStruct.new(one: '', two: '') # works on runtime, no static error
SomeStruct.new(one: '', two: 1) # fails on runtime because of type mismatch, no static error
SomeStruct.new(one: '', two: '', three: '') # fails on runtime because of extra argument, no static error
我有一个结构定义为:
# typed: true
require 'sorbet-runtime'
class MyStruct < T::Struct
MyPropType = T.type_alias { T::Hash[Symbol, Class] }
class << self
extend T::Sig
sig { params(props: MyPropType).void }
def register_props(props)
props.each do |prop_name, prop_type|
prop(prop_name, prop_type)
end
end
end
end
注意 prop
是如何在运行时定义的。
然后在我的代码库的某个地方,在启动时,我做 MyStruct.register_props({ foo: T.untyped, bar: T.nilable(T.untyped) })
。
初始化 MyStruct
在通过类型检查传递代码库时出错。 MyStruct.new(foo: 'foo', bar: Bar.new)
.
$ ./bin/srb typecheck
/path/to/file.rb:66: Too many arguments provided for method MyStruct#initialize. Expected: 0, got: 1 https://srb.help/7004
如何在运行时在 T::Struct
上定义 prop
s 而不会出现上述类型检查错误?
AFAIK T::Struct
s 不能动态定义(我的意思是他们可以但是......),因为类型检查器需要静态地知道它将拥有哪些道具。对于这种情况,我认为您应该使用 T::InexactStruct
。参见 https://github.com/sorbet/sorbet/blob/master/gems/sorbet-runtime/lib/types/struct.rb
编辑:添加片段以供将来参考
# typed: strict
class SomeStruct < T::InexactStruct
extend T::Sig
sig { params(props: T::Array[T.untyped]).void }
def self.register(props)
props.each do |name, type|
prop name, type
end
end
end
SomeStruct.register [[:one, String], [:two, String]]
SomeStruct.new() # This would raise an error on runtime because of missing arguments, but not on static check
SomeStruct.new(one: '', two: '') # works on runtime, no static error
SomeStruct.new(one: '', two: 1) # fails on runtime because of type mismatch, no static error
SomeStruct.new(one: '', two: '', three: '') # fails on runtime because of extra argument, no static error