Tengo una estructura que se define como:
# 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 Observe cómo se definen prop s en tiempo de ejecución.
Luego, en algún lugar de mi base de código, al inicio, hago MyStruct.register_props({ foo: T.untyped, bar: T.nilable(T.untyped) }) .
La inicialización MyStruct error al pasar el código base a través de la verificación de tipos. 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 ¿Cómo defino prop s en T::Struct en tiempo de ejecución sin el error de verificación de tipo anterior?
AFAIK T::Struct s no se pueden definir dinámicamente (quiero decir que pueden pero...), ya que el verificador de tipos necesita saber estáticamente qué accesorios va a tener. Para este caso, creo que deberías usar T::InexactStruct . Consulte https://github.com/sorbet/sorbet/blob/master/gems/sorbet-runtime/lib/types/struct.rb
EDITAR: Agregar fragmento para futuras referencias
# 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