I’d like to double-check my understanding of binding to external functions with polymorphic values. I’m creating a new binding to a react component. What I’d like to do is something like this:
A glance at the docs and a search through this forum seems to confirm this is the standard approach.
This is fine for my usually limited use cases, but not ideal if the component has multiple overloaded properties and you’re trying to write flexible bindings for general use for everyone. i.e.- You don’t really want to write a make function for all permutations of prop options.
module Make = (T: { type t }) => {
@module("react-native-paper") @scope("Drawer") @react.component
external make: (~label: string=?, ~badge: T.t=?) => React.element =
"CollapsedItem"
}
module StringItem = Make({ type t = string })
module IntItem = Make({ type t = int })
let items =
<>
<StringItem label="String" badge="ok" />
<IntItem label="Int" badge=42 />
</>
And you could use functors inside functors to generate permutations of different types. But IMO this sounds like such a messy API that I’d probably just create a wrapper API with a proper data model instead.
Yep, that would work! It does result in potentially less LOC on my end, but still results in bindings where the user has to choose between components StringItem and IntItem, or in an expanded example: CollapsedItemWithStringBadgeAndIntThing, CollapsedItemWithStringBadgeAndStringThing, CollapsedItemWithIntBadgeAndIntThing, etc. … That said, thanks for chiming in, it’s prob an approach I need to consider playing around with.
There’s prob a good language/type-specific reason as to why this choice ultimately gets hoisted up to the component level, but it would be nice if there was a good way to handle it at the individual prop level, especially where individual props are optional (in my case they all are) and the overhead of creating separate components for various ones adds a lot of seemingly needless overhead.
You could use abstract type to represent all the different things you may want to pass in to the parameter. Then use that as the type for the parameter.
module Badge = {
type t
external s: string => t = "%identity"
external i: int => t = "%identity"
external f: float => t = "%identity"
external b: bool => t = "%identity"
}
module CollapsedItem = {
@module("react-native-paper") @scope("Drawer") @react.component
external make: (~label: string=?, ~badge: Badge.t=?) => React.element =
"CollapsedItem"
}
let y = <CollapsedItem badge={Badge.s("yo")} />
let z = <CollapsedItem badge={Badge.i(123)} />