【问题标题】:How to convert a Js.Dict.t to Js.t in ReScript?如何在 ReScript 中将 Js.Dict.t 转换为 Js.t?
【发布时间】:2020-12-01 22:20:20
【问题描述】:

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

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

Js.t 喜欢这个:

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

【问题讨论】:

    标签: reason bucklescript rescript


    【解决方案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";
    

    这里指定返回的对象具有与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
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多