Type constraints

I’m looking into using Domain Driven Design along with ReScript.

And let’s say I wanted a type that would make sure a string is never empty and at most 25 chars long. Something like type string25 = …

I’m not sure what would be an idiomatic way to handle this in ReScript.

Does Variants allow for custom logic in the constructors? Or how would you approach this?

1 Like

@mellson the idea is to wrap the type in a module and use like this :point_down:t3:

module String25: {
  type t
  let make: string => Belt.Result.t<t, string>
} = {
  type t = string
  let make = a =>
    a->Js.String.length <= 25
      ? Belt.Result.Ok(a)
      : Belt.Result.Error("String must be 25 letters utmost")
}

let safeString: Belt.Result.t<String25.t, string> = String25.make("Some string")
9 Likes

Thanks, this was very helpful :+1:t2:

1 Like

The way in Rescript is to use a module, and use code to protect the values you are concerned about.

You can build type systems which can handle logic rules on types, but those systems are not present in ReScript (and arguably still somewhat of a research area). I know of at least 3 general variants:

  • Lattice based systems. See e.g., CUE for a use.
  • Refinement types
  • Dependent types

The tricky part of these systems are that you need the type check to happen at compile time. And you open the door for having general logic in the type system. So the type checker might run for a long time, perhaps not even terminate.

2 Likes