Turn type (polymorphic variant) into values?

Is there a way to convert a type to values?

My use case is that I have this type:

type rgb = [ #Red | #Green | #Blue ]

And I’d like to force the user to choose between one of the three in a dropdown.

If it is a string value that you want to convert to then, Polymorphic variants without any parameters, actually compiles to a string. You can check this playground link (check the js output).

However it is better to deliberately convert it using a function like this.

let convertToString = (rgb: rgb) =>
  switch rgb {
  | #Red => "Red"
  | #Green => "Green"
  | #Blue => "Blue"
  }
1 Like

Thanks, I am doing something similar to that now.

My question was more if it’s possible to convert the entire type to a string array without having to type each case :thinking:

You can actually do

let rgbToStr = (x: rgb) => {
  (x :> string)
}

but I think @mellson is looking for generating a set/list of available variants.
I don’t think if it’s possible without using a ppx.

3 Likes

Thanks @amiralies - you’re right I was looking for a way to convert. But a ppx would be overkill, I was just trying to see if I was missing some built-in functionality :slight_smile:

Does it have any advantage over external rgbToStr: rgb => string = "%identity"?

I take it you don’t care about localization? Because automatic conversion is obviously not i18n-friendly.

The :> (coercion) operator only works when the type of lefthand side is subtype of righthand so
if you add a case to your variant which is not subtype of string (for example #Other(string)) you will get a type error.

4 Likes

Got a solution working :wink:

If I add @deriving(jsConverter) to the enum there’s a free string to enum convertor.
Then we just iterate all the words and voila we have converted the type into values.

@deriving(jsConverter)
type rgb = [#Red | #Green | #Blue]

let allTheKnownWordsInTheUniverse = [...]

let rgbValues = allTheKnownWordsInTheUniverse->Array.map(rgbFromJs)->Array.keep(Option.isSome)

There’s a few performance reasons before I put it into production though :laughing: