Can be either types

Hi, I’m trying some luxon library binding for learning purpose.

Here is what I’ve got sofar :

type zone = {
  \"type": string,
  name: string,
  isUniversal: bool,
}

type options = {
    // does not compile
    // zone: zone | string

    // ok
    zone: zone,
}

module DateTime = {
    type t
    @send external fromISO: (string, options) => t = "fromISO"
}

How do I tell compiler zone option can be either a string or a zone ?

You can’t make TS-style type unions in ReScript. You have to be stricter on typing. A straightforward way would be using a variant:

type zone = { ... }

type zoneOption =
  | String(string)
  | Zone(zone)

but in this case, you have to properly encode option values before passing to JavaScript because the internal representation of zoneOption will not be plain zone | string:

module DateTime = {
    type t

    // Private weak binding
    @send external _fromISO: (string, 'options) => t = "fromISO"

    // Public strong binding
    let fromISO = (iso, zone) =>
      switch zone {
      | Zone(zone) => _fromISO(iso, {"zone": zone})
      | String(zone) => _fromISO(iso, {"zone": zone})
      }
}
1 Like

For a runtime-free version, you can also write two different bindings:

type zone = {\"type": string, name: string, isUniversal: bool}

type options<'a> = {zone: 'a}

module DateTime = {
  type t
  @send external fromISO: (string, options<string>) => t = "fromISO"
  @send external fromISOZone: (string, options<zone>) => t = "fromISO"
}
7 Likes