如何为联合类型编写Reasonml绑定

时间:2018-09-12 14:05:36

标签: ocaml ffi reason bucklescript union-types

我正在尝试为https://github.com/oblador/react-native-keychain/blob/master/typings/react-native-keychain.d.ts#L76编写绑定

如果出错,

getGenericPassword返回false,否则返回objectcredentials)。我不确定这种联合类型是否可以合理地表示,但是更好的API是选项(option(credentials))的结果。但是,如何在绑定文件中转换Promise<boolean | credentials>-> Js.Promise.t(option(credentials))。下面是一个模板。

感谢您的帮助。

[@bs.deriving abstract]
type credentials = {
  service: string,
  username: string,
  password: string,
};

/* TODO convert the actual return value 
Js.Promise.t(option(credentials)) to more reason type 
Js.Promise.t(option(credentials)) */

[@bs.module "react-native-keychain"] [@bs.scope "default"]
external getGenericPassword: unit => Js.Promise.t(option(credentials)) = "";

1 个答案:

答案 0 :(得分:6)

您可以使用Js.Types.classify获取值的运行时类型。

type maybeCredentials;

[@bs.module "react-native-keychain"] [@bs.scope "default"]
external getGenericPassword: unit => Js.Promise.t(maybeCredentials) = "";

let getGenericPassword: unit => Js.Promise.t(option(credentials)) =
  () =>
    Js.Promise.(
      getGenericPassword()
      |> then_(maybeCredentials =>
           switch (Js.Types.classify(maybeCredentials)) {
           | JSObject(obj) => resolve(Some(obj |> Obj.magic))
           | _ => resolve(None)
           }
         )
    );

这里maybeCredentials被定义并用作中间类型。

然后,我们定义一个与绑定名称相同的函数,该函数将“遮盖”该名称,并防止直接使用绑定以支持我们的“覆盖”。但是,在 内,我们仍然可以使用绑定。

然后,我们调用Js.Types.classify以获取返回值的运行时类型。如果是对象,则使用Obj.magic将抽象obj_type转换为我们的credentials类型(从函数的返回类型推断),并将其包装在option中。对于其他任何类型,我们都返回None

顺便说一句,这种“类型”称为无标签联合。我在bucklescript-cookbook中写下了一些使用不同策略(作为生产者和消费者)使用这些策略的示例。