Bind strings output by a JS function to a variant

I import a JS function into my ReScript code and I have been able to bind it correctly. The function outputs predictable strings, let’s say, "dog", "cat" and "bird".
Because the function cannot output another string outside of these three, is it possible to turn the strings into a variant in ReScript, for example, Dog | Cat | Bird? That would make pattern-matching available and it would be safer to use the output.
Thanks!

The only thing that pops into my mind would be to bind the function in question as private (returning just a string) and then create a public version that calls the bound version and then pattern match it to make a type-variant.

@val external _myFunc: unit => string = "myFunc"

type myVariants = Dog | Cat | Bird

let myFunc = () => switch _myFunc() {
  case "dog" => Dog
  case "cat" => Cat
  case "bird" => Bird
}
1 Like

The simplest way is to use a polyvariant, since that has a runtime representation as string:

https://rescript-lang.org/try?version=v10.1.2&code=C4TwDgpgBAhgdgSwLYwDYGcoF4oG0DEAJgPYDmUAPlPgMYzCXUBGCAToQLoBQXAAgG5ooEAB7AIrOEKQgAgohSoAYnABcUAK6IGWAHywFaTDgBEM+cjQqTPAFLoAdKjIAKLlCjoA7gmA0AFlDmhspwLgCUUADe7oxEZNj6JrJQJKQ2HlS09IlQyVB0wBlxLOy5+aWExQC+ADRc4VxAA

4 Likes

Both are great solutions, thank you!
FYI, I don’t know who takes care of the documentation, but there is no mention that pattern matching over strings is possible, it is mentioned for arrays, lists, etc., but not for strings, so I wasn’t sure if it was possible. It could be interesting to add it.

1 Like

I think that’s fair since the guide doesn’t explicitly mention you can use any literal as an arm for a switch, but I’d guess they assumed a user would infer that since that’s how switch statements work on Javascript. Nonetheless, it’s mentioned as a side note explaining you can only use literals and not arbitrary let-binding expressions.