Say I have a global object called Example
, which has a constructor such that new Example()
returns an object with a key called "Messaging"
Say I have the following Reason/Bucklescript Code:
[@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 results in:
This expression has type wrappedExample
It has no method messaging
Changing the last line to:
exampleConstructor()##messaging
or exampleConstructor().messaging
similiarly fails. What is the issue here? How can I access my javascript value?
You seem to be conflating a bunch of things here that are similar, but don't really work together.
So first of all,
#
is used for accessing the field of an OCaml object.##
is used to access the field of aJs.t
object, which is not what you have here (I'll explain why in a minute).[@bs.deriving abstract]
is a different concept fromJs.t
and will not create an object type of any kind, but produces an abstract type (this is whatabstract
in thebs.deriving
annotation hints at). An abstract type has no "structure" in itself, so you can't do anything with it directly. And wrapping it inJs.t
does not make it a JS object type, just an abstract type wrapped inJs.t
(aJs.t
object type is specifically an OCaml object type wrapped inJs.t
).The key to this is that
[@bs.deriving abstract]
doesn't just create an abstract type, but also a number of functions that operate on it. For every field it creates a getter suffixed withGet
,messagingGet
in your case, and if mutable a setter suffixed withSet
. There's also a creation function named after the type and with the fields as labeled arguments, so in your case you can create an object withexample(~messaging="whatever")
. See the BuckleScript documentation for details.Here's a fixed version of your example:
If you think this is all very confusing, that's because it is. I have no clue what they're doing anymore, but it seems very messy to me too. I would recommend skipping
[@bs.deriving abstract]
entirely and instead create the abstract type and accessors yourself using ordinaryexternal
s. There's much less confusing magic and terrible naming of things that way.