Как преобразовать Js.Dict.t в Js.t в ReScript?
Есть ли простой способ преобразовать
Js.Dict.t
как этот
Js.Dict.fromArray([
("bigKey", Js.Dict.fromArray([("smallKey", "value")]))
])
к
Js.t
как этот:
{
"bigKey": {
"smallKey": "value"
}
}
1 ответ
По структуре они уже одинаковы - оба представлены как объекты JavaScript - поэтому технически нет необходимости "преобразовывать" их. Несмотря на то, что они одинаковы по структуре, типы различаются взаимоисключающими способами, и поэтому нет никакого способа преобразовать один в другой в целом.
Js.Dict.t
представляет собой однородную коллекцию из неизвестного числа пар ключ-значение, а
Js.t
представляет собой разнородный набор фиксированного числа пар ключ-значение, хотя он также поддерживает подтипы и в сочетании с выводом типов может показаться динамическим.
Так что самый простой способ сделать это - просто преобразовать его в "открытый" объектный тип, который будет выводиться таким, каким вы хотите его видеть:
external dictToJsObject : Js.Dict.t(_) => Js.t({..}) = "%identity";
Но будьте осторожны, здесь нет безопасности типов на клавишах. Компилятор просто предполагает, что вы его используете правильно. Если вы используете ключ, предполагается, что он существует, и ограничение типа значения из
Js.Dict.t
не переносится и не согласовывается между ключами.
Немного лучший подход - преобразовать его в "закрытый" тип объекта с известной формой:
external dictToJsObject : Js.Dict.t('a) => Js.t({ "foo": 'a, "bar": 'a }) = "%identity";
Здесь указывается, что возвращаемый объект имеет ключи
foo
и
bar
с тем же типом значения, что и
Js.Dict.t
. Это обеспечивает значительно большую безопасность типов, но мы все еще не можем знать во время компиляции, что
foo
и
bar
ключи действительно существуют в
Js.Dict.t
. Мы просто предполагаем, что это так.
Следовательно, единственный правильный способ преобразовать
Js.Dict.t
к
Js.t
обычно это делается вручную:
let dictToJsObjec
: Js.Dict.t('a) => option({"foo": 'a, "bar" 'a})
= dict =>
switch ((Js.Dict.get(dict, "foo"), Js.Dict.get(dict, "bar"))) {
| (Some(foo), Some(bar)) => Some({
"foo": foo,
"bar": bar,
})
| _ => None
}