Edit: updated for JSX3 on June 5 2019

How to use ReasonML parametric types on a ReasonReact component

Suppose you have the following code (we are using genType to make our life easier here btw — we’ll post about it):



[@genType]

type state = {data: array(string)}; type state = {data: array(string)}; @genType]

type renderItemBag = {

item: string,

index: int,

move: unit => unit,

moveEnd: unit => unit,

isActive: bool,

}; type renderItemBag = {item: string,index: int,move: unit => unit,moveEnd: unit => unit,isActive: bool,}; [@bs.module "react-native-draggable-flatlist"]

[@react.component]

external make:

(

~data: array(string),

~keyExtractor: string => string,

~scrollPercent: int,

~renderItem: renderItemBag => React.reactElement,

~onMoveEnd: state => unit,

array(React.element)

) =>

React.element =

""; ...Usage... <DraggableFlatList

data=[|"fubá", "corn", "cheese", "pork"|]

scrollPercent=15

renderItem=(MyItem.foo)

onMoveEnd=foo />

With this code you limit your users to have always “string” item type, but what if you want to give your user the ability to use any kind of item type? Parametric types to the rescue:

@genType]

type state('item) = {data: array('item)}; type state('item) = {data: array('item)}; @genType]

type renderItemBag('item) = {

item: 'item,

index: int,

move: unit => unit,

moveEnd: unit => unit,

isActive: bool,

}; type renderItemBag('item) = {item: 'item,index: int,move: unit => unit,moveEnd: unit => unit,isActive: bool,};

[

external make:

(

~data: array('item),

~keyExtractor: 'item => string,

~scrollPercent: int,

~renderItem: renderItemBag('item) => React.element,

~onMoveEnd: state('item) => unit,

'a

) =>

React.element =

""; @ bs.module "react-native-draggable-flatlist"] @ react.component]external make:~data: array('item),~keyExtractor: 'item => string,~scrollPercent: int,~renderItem: renderItemBag('item) => React.element,~onMoveEnd: state('item) => unit,'a) =>React.element =""; ...Usage now, anything!... <DraggableFlatList

data=[|"fubá", "corn", "cheese", "pork"|]

scrollPercent=15

renderItem=(MyItem.foo)

onMoveEnd=foo /> ...Usage... <DraggableFlatList

data=[|{ "name": "Bitcoin"}, {"name": "Ethereum"}|]

scrollPercent=15

renderItem=(({ item }) => <Item name={item ^ "foo"} />) /* compiler throws here as it detects item is not a string, it's a { . "name": string } */

onMoveEnd=foo />

The syntax for a parametric type goes as: type name('param) = foo;

You can even read it as a “parameter type to a type function”. And you can have as many as you want: type name('a, 'b, 'c, 'd) = ...;

Having the type parametric `item`and giving it the same name across params the compiler ensures for us that once it infers the first `‘item` all will follow the same type.

More examples of it in action:

https://github.com/reasonml-community/bs-react-native/blob/master/src/components/flatList.re#L51