Подпись сорбета для вложенного хеша - PullRequest
0 голосов
/ 10 июля 2020

У меня есть метод, который анализирует файлы YAML. Возвращаемый объект - это вложенный Ha sh, где ключи всегда являются строками, а конечные значения всегда являются строками, например,

{
    "a" => "foo",
    "b" => {
        "c" => "bar",
        "d" => "baz"
    }
}

Я не знаю заранее, насколько глубоко ha sh есть.

Ближе всего к вводу возвращаемого значения мне подошла следующая подпись:

T.any(T::Hash[String,String], T::Hash[String,T::Hash[String, T.untyped]])

Это, очевидно, плохое решение, поскольку оно не проверяет ничего ниже второго вложения, но документация о настраиваемых типах кажется немного скудной.

Есть ли способ ввести вложенные хэши, используя настраиваемый тип, вложенные типы или что-то подобное?

1 Ответ

1 голос
/ 20 июля 2020

К сожалению, на данный момент вы не сможете сделать намного больше, чем должны. Несмотря на то, что Shapes поддерживаются, это экспериментальная функция.

Если вы действительно хотите go с хешами, вы можете express это как:

MyType = T.type_alias {T::Hash[String, T.any(String, T::Hash[String, T.untyped])]}

В качестве альтернативы вы можете использовать T::Struct:

class MyType < T::Struct
  const :key, String
  const :value, T.any(String, MyType)
end

У вас все еще будет неуверенность в том, какой тип value, но с чувствительность к потоку , структура должна легко обрабатываться:

class Processor
  extend T::Sig
  
  sig {params(my_object: MyType).returns(String)}
  def process(my_object)
    key = my_object.key
    obj_value = my_object.value # this is needed for flow sensitivity below
    value = case obj_value
    when String
      value
    when MyType
      process(obj_value)
    else
      T.absurd(obj_value) # this makes sure that if you add a new type to `value`, Sorbet will make you handle it
    end
    return "key: #{key}, value: #{value}"
  end
end
...