如何在ReScript中将Js.Dict.t转换为Js.t



有没有直接的方法来转换像这样的Js.Dict.t

Js.Dict.fromArray([
("bigKey", Js.Dict.fromArray([("smallKey", "value")]))
])

到像这样的Js.t

{
"bigKey": {
"smallKey": "value"
}
}

从结构上看,它们已经是相同的——都表示为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";

这里,返回的对象被指定为具有与Js.Dict.t具有相同值类型的密钥foobar。这提供了更多的类型安全性,但在编译时我们仍然无法知道foobar密钥实际上存在于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
}

相关内容

  • 没有找到相关文章

最新更新