2

假设我有一个名为 的全局对象Example,它有一个构造函数,它new Example()返回一个对象,其键名为"Messaging"

假设我有以下原因/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

4

1 回答 1

4

您似乎在这里混淆了一堆相似的东西,但并没有真正一起工作。

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

[@bs.deriving abstract]是一个不同的概念,Js.t不会创建任何类型的对象类型,但会产生一个抽象类型(这是abstract注释中所bs.deriving暗示的)。抽象类型本身没有“结构”,所以你不能直接用它做任何事情。并且将其包装在其中Js.t并不会使其成为 JS 对象类型,而只是将其包装在中的抽象类型Js.tJs.t对象类型具体是 OCaml 中包装的对象类型Js.t)。

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

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

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

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

exampleConstructor() |> messagingGet;

如果您认为这一切都非常令人困惑,那是因为它是。我不知道他们在做什么了,但对我来说似乎也很混乱。我建议[@bs.deriving abstract]完全跳过,而是使用普通external的 s 自己创建抽象类型和访问器。以这种方式对事物进行令人困惑的魔法和可怕的命名要少得多。

于 2018-10-08T22:17:47.523 回答