Binding to an option value

What is the difference in

~getValueFromEvent: ReactEvent.Form.t=?,//option<ReactEvent.Form.t> ?

and

~getValueFromEvent: option<ReactEvent.Form.t>=?,//option<option<ReactEvent.Form.t>> ?

in something like this?

module Item = {
  @react.component @module("lib")
  external make: (
    ~getValueFromEvent: ReactEvent.Form.t=?,
    ~getValueFromEvent: option<ReactEvent.Form.t>=?,
  ) => React.element = "Item"
}

Thanks

1 Like

The second is wrong. It will become option<option<ReactEvent.Form.t>> in the type system.

3 Likes

This is a bit confusing to me as well, for example this won’t compile:

module Hello = {
  @react.component
  let make = (~name1: string=?, ~name2: option<string>=?) => {
    switch name1 {
    | None => React.null
    | Some(name) => <div> {React.string(name)} </div>
    }
  }
}

But this will:

module ExternalHello = {
  @react.component @module("./hello")
  external make: (~name1: string=?, ~name2: option<string>=?) => React.element =
    "default"
}

module Greeting = {
  @react.component
  let make = () => {
    <ExternalHello name1="Steve" name2="Rogers" />
  }
}

In that I was expecting the compiler to either complain that name1 in the external binding should be an option<string> or that name2 in the Greeting module should be wrapped as Some("Rogers").

rescript playground

This is a quirk for optional arguments. I thought that the docs addressed it somewhere, but I can’t find it now.

The key difference is whether the type annotation is for the entire function or just an argument. Here’s an example that shows the difference.

let f: (~foo: string=?) => string = (~foo: option<string>=?) =>
  switch foo {
  | None => ""
  | Some(x) => x
  }

The entire function f is annotated as (~foo: string=?) => string. This what code outside of the function sees. foo is a string because outside code will call it like f(~foo="bar").

The inline type annotation for foo is option<string> though, because that’s what code inside the function sees.

This is why your two type annotations look different. ExternalHello.make has its entire function’s type signature annotated, while Hello.make only annotates individual arguments inside the function.

5 Likes