假设我有一个名为Example
的全局对象,该对象具有一个构造函数,使得new Example()
返回一个带有名为"Messaging"
的键的对象
说我有以下原因/验证码:
[@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()##messaging
或exampleConstructor().messaging
类似地失败。这是什么问题?如何获取我的javascript值?
答案 0 :(得分:4)
您似乎在这里混淆了很多类似的东西,但并没有真正一起工作。
因此,首先,#
用于访问OCaml对象的字段。 ##
用于访问Js.t
对象的字段,这不是您在此处所拥有的(稍后我将解释原因)。
[@bs.deriving abstract]
是与Js.t
不同的概念,它不会创建任何类型的对象类型,但是会产生抽象类型(这就是abstract
bs.deriving
注释中的提示)。抽象类型本身没有“结构”,因此您不能直接对其进行任何操作。并且将其包装在Js.t
中并不会使其成为JS对象类型,而只是将其包装在Js.t
中的抽象类型(Js.t
对象类型是包装在{{1}中的OCaml对象类型}。
关键是Js.t
不仅会创建抽象类型,而且还会创建许多对其进行操作的函数。对于每个字段,它都会创建一个后缀为[@bs.deriving abstract]
,Get
的getter,并且如果可变,则会创建一个后缀为messagingGet
的setter。还有一个创建函数,该创建函数以类型命名,并将字段标记为自变量,因此在您的情况下,可以使用Set
创建对象。有关详细信息,请参见the BuckleScript documentation。
这是您的示例的固定版本:
example(~messaging="whatever")
如果您认为这一切都很令人困惑,那是因为。我不知道他们在做什么,但对我来说也很混乱。我建议完全跳过[@bs.deriving abstract] type example = {
[@bs.as "Messaging"] messaging: string
};
[@bs.new] external exampleConstructor: unit => example = "ExampleThing";
exampleConstructor() |> messagingGet;
,而创建抽象类型并使用普通的[@bs.deriving abstract]
自己访问。这样,对事物的神奇和可怕的命名就没有那么混乱了。