#reason #bucklescript #rescript
#Причина #bucklescript #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
. Мы просто предполагаем, что это так.
Следовательно, единственный правильный способ преобразовать a Js.Dict.t
в a 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
}