ReasonML 访问 JS 记录字段

ReasonML access JS record field

假设我有一个名为 Example 的全局对象,它有一个构造函数使得 new Example() returns 一个具有名为 "Messaging"

键的对象

假设我有以下 Reason/Bucklescript 代码:

[@bs.deriving abstract] type example = {
  [@bs.as "Messaging"] messaging: string
};

type wrappedExample = Js.t(example);

[@bs.new] external exampleConstructor: unit => wrappedExample = "ExampleThing";

exampleConstructor()#messaging;

这导致:

This expression has type wrappedExample
It has no method messaging

将最后一行更改为:

exampleConstructor()##messagingexampleConstructor().messaging 同样失败。这里的问题是什么?如何访问我的 javascript 值?

https://reasonml.github.io/en/try?rrjsx=true&reason=NoAQRgzgdAJgpgJwJYDckDsDmACAhpAFwVwGMCBdbAgTwAc5s4APXAW1oBsGBebAbwBQ2bKEhRcEbACIAsnAgRcmDJimVW8xcqwAubBCIqBAXwDcAgTXrYA7sVr0YAURbsu2XgCloBABTM2TjgASnMBUWh0OBtKZgJEdFwORlcggGEAe3QDBABXMgyEPVz0JAIPAD5be0cXQPdeKTq3OAAVAAsVKTCAlszsonyCQt9ggGINBSUVUyA

你似乎把一堆相似的东西混为一谈,但实际上并没有一起工作。

所以首先,#用于访问OCaml对象的字段。 ## 用于访问 Js.t 对象的字段,这不是你这里的(我稍后会解释原因)。

[@bs.deriving abstract] 是与 Js.t 不同的概念,不会创建任何类型的对象类型,而是生成一个 抽象类型 (这就是abstractbs.deriving 注释中提示)。抽象类型本身没有 "structure" ,所以你不能直接对它做任何事情。而包裹在Js.t中并不能使它成为JS对象类型,只是包裹在Js.t中的抽象类型(Js.t对象类型具体是包裹在[=13=中的OCaml对象类型]).

关键是 [@bs.deriving abstract] 不仅创建了一个抽象类型,而且还创建了一些对其进行操作的函数。对于每个字段,它都会创建一个 getter 后缀为 Get,在您的情况下为 messagingGet,如果可变 setter 后缀为 Set。还有一个以类型命名的创建函数,并将字段作为标记参数,因此在您的情况下,您可以使用 example(~messaging="whatever") 创建一个对象。有关详细信息,请参阅 the BuckleScript documentation

这是您的示例的固定版本:

[@bs.deriving abstract] type example = {
  [@bs.as "Messaging"] messaging: string
};

[@bs.new] external exampleConstructor: unit => example = "ExampleThing";

exampleConstructor() |> messagingGet;

如果您认为这一切都非常令人困惑,那是因为它确实如此。我不知道他们在做什么,但对我来说也很混乱。我建议完全跳过 [@bs.deriving abstract],而是使用普通的 external 自己创建抽象类型和访问器。这样就可以减少令人困惑的魔术和可怕的命名方式。