Merging prop definitions

When writing components, we often want to combine props specific to a certain component with other, more general props like JsxDOM.domProps. Take, for example, the bindings HeadlessUI.Transition used for rescript-lang.org:

module Transition = {
  @module("@headlessui/react) @react.component
  external make: (
    ~appear: bool=?,
    ~show: bool,
    ~enter: string=?,
    ~enterFrom: string=?,
    ~enterTo: string=?,
    ~leave: string=?,
    ~leaveFrom: string=?,
    ~leaveTo: string=?,
    ~children: React.element,
  ) => React.element = "Transition"
}

Rest below. Sorry, had to split up the post due to the new user policy…

Here, we have the props specific to HeadlessUI.Transition (appear, show, ...), but I also want to be able to pass generic dom props (e.g. ariaHidden). As props are nominally typed nowadays, we need to be able to merge our prop definitions somehow.

As there no way to let a function derive its parameter set from a record type definition, we cannot use @react.component in this case, right?

So, we have to use something that excepts a plain record as props. With record spreading coming in v11, I have the following solutions in mind:

When writing our own components, that would mean we have to write our component by hand, like shown in the docs:

// should work in v11

module Link = {
  type props = {...JsxDOM.domProps, href: string, children: React.element};
  
  let make = (props: props) => { 
    <a href={props.href}>
     {props.children}
    </a>
  }
}

<Link href="/docs"> {React.string("Docs")} </Link>

Further, for externals we can use the trick I recently learned from @mvaled, and bind our make to the @scoped render method:

// should work in v11

module Transition = {
  type props = {
    ...JsxDOM.domProps,
    appear: bool=?,
    show: bool,
    enter: string=?,
    enterFrom: string=?,
    enterTo: string=?,
    leave: string=?,
    leaveFrom: string=?,
    leaveTo: string=?,
    children: React.element
  }

  @module("@headlessui/react) @scope("Transition")
  external make: props => React.element = "render"
}

I have a few questions, though:

  • Are those the best ways so achieve what I want?
  • What is the canonical way to merge prop definitions in v10?
  • Is there a way to derive function parameters sets from record type definitions (i.e. the reverse of what react.component does with make’s labeled arguments) I’m not aware of? If not, is something like this planned?