ReasonML доступ к полю записи JS

Скажем, у меня есть глобальный объект с именем Example, у которого есть конструктор, такой, что new Example() возвращает объект с ключом "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()##messaging или exampleConstructor().messaging также терпят неудачу. В чем проблема? Как я могу получить доступ к своему значению javascript?

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


person Abraham P    schedule 08.10.2018    source источник


Ответы (1)


Кажется, вы объединяете здесь кучу похожих вещей, но на самом деле они не работают вместе.

Итак, в первую очередь, # используется для доступа к полю объекта OCaml. ## используется для доступа к полю объекта Js.t, а это не то, что у вас здесь (я объясню почему через минуту).

[@bs.deriving abstract] представляет собой концепцию, отличную от Js.t, и не создает никаких типов объектов, а создает абстрактный тип (на это указывает abstract в аннотации bs.deriving). Абстрактный тип сам по себе не имеет «структуры», поэтому вы ничего не можете сделать с ним напрямую. И упаковка его в Js.t не делает его типом объекта JS, а просто абстрактным типом, завернутым в Js.t (тип объекта Js.t - это, в частности, тип объекта OCaml, завернутый в Js.t).

Ключ к этому в том, что [@bs.deriving abstract] создает не только абстрактный тип, но и ряд функций, которые с ним работают. Для каждого поля он создает геттер с суффиксом Get, messagingGet в вашем случае и, если изменяемый, сеттер с суффиксом 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. Таким образом становится гораздо меньше запутанной магии и ужасных названий вещей.

person glennsl    schedule 08.10.2018