I wonder if anyone else has had similar ideas.
Composition and extension can be a bit tedious at times, especially for components with many prop fields. It can also be error prone to compose components since optional fields can be omitted by accident.
module Lib = {
type props = {
a: string,
b?: string
}
let make: React.component<props> = Js.Exn.raiseError("")
}
module NumericComponent = {
type props = {
a: string,
b: float // formats a float nicely to a string
}
let make = (p: props) => Lib.make({a: p.a})
}
Are there any practical reasons why props is not a module instead?
They have support … for types via include.
module type P1 = {
let a: string
let b: string
}
module type P2 = {
let b: float
}
module type P3 = {
include P1
include P2
}
Here is a full example.
module BaseComponent = {
module type Props = {
let name: string
let age: int
let height: int
}
let make = (module(P: Props)) => {
open P
<>
{name->React.string}
{age->Belt.Int.toString->React.string}
{height->Belt.Int.toString->React.string}
</>
}
}
module Extension = {
module type Props = {
include BaseComponent.Props
let height: float // new datatype for height
}
let make = (module(P: Props)) =>
BaseComponent.make(
module(
{
include P
let height = height->Belt.Float.toInt
}
),
)
}
let comp = React.createElement(
Extension.make,
module(
{
let name = "John"
let age = 42
let height = 1.8
}
),
)
let comp = <Extension
{...module(
{
let name = "John"
let age = 42
let height = 1.8
}
)}
/>
The abilities of modules are available like functors.
I am unsure if anything akin to the ? modifier on types exists for modules (I would guess it’d equate to a default value for the field).
Syntatic work is needed to make it look as nice as jsx attributes. I don’t think that the equivalent of type parameters, abstract types, is inferrable, so that is another potential painpoint.