Skip to main content

Union Values

Union differences

While is is great to have a consistent usage for passing union values as props, it can come at a conversion cost. This is why the current bindings make a difference between 3 types of union values.

String only unions

Whenever a prop on a component consists of a selection of string only literals, the generator will create polymorphic variants which just happen to compile to JS strings anyway.

This is an example of the prop variant, taken from Mui.Accordion.res:

type variant = [#elevation | #outlined]

You can use it like so:

<Mui.Accordion variant=#outlined />

Rules for string only unions

  • All polymorphic variants have the same case as the original string value now (mostly lowercase)
  • Some values include invalid characters (like -), which makes it necessary to use quotes, e.g.: #"flex-end"

Additional types

In case that you need to pass around the type of a string union prop, the generator creates a helper type for you in the module. To continue the example from earlier, the following helper type will be added to Mui.Accordion.res:

type variant = [#elevation | #outlined]

Numeric unions

Numeric unions now work the same way as string only unions now and don't utilize the @int directive anymore.

These don't happen often - currently the only place where this applies is in the Mui.Grid.res component.

Example usage:

<Mui.Grid spacing=#2 />

Mixed unions

Mixed unions make use of the ReScript's unboxed decorator: [unboxed]. The nice thing about unboxed is, that there is no conversion cost, just as with the above ones. Some of the helper functions will leave a function in the generated js, that just returns the one argument it gets passed. These can be stripped easily with an optimization build step (e.g. with webpack).

Whenever a prop value can be a literal of multiple types, this way of typing it is used. A module inside of the component is created, that is simply named after the prop (uppercased).

Let's use the component prop of the Grid component as an example. We can pass either a string, callback or element as the component prop. This will generate the following module inside the Grid component file:

module Component: {
type t
let string: string => t
let callback: (unit => React.element) => t
let element: React.element => t
} = {
@unboxed
type rec t =
| Any('a): t
let string = (v: string) => Any(v)
let callback = (v: unit => React.element) => Any(v)
let element = (v: React.element) => Any(v)
}

You can use it in the following way:

open Mui
<div>
<Grid component=Grid.Component.string("div") />
<Grid component=Grid.Component.element(<div />) />
</div>

Rules for mixed unions

  • Always creates a module leveraging @unboxed with the uppercased name of the prop
  • Always fills that module with helper functions that are named after the type they represent
  • Literal values don't have helper functions, but are represented as let bindings
  • Numeric literals are always prefixed with _ (e.g. Grid.Md._2)
  • Boolean literals are always prefixed with _ (e.g. Grid.Md._false)
  • String literals are always their lowercased self (e.g. Grid.Md.auto)