In my applications, I’m using a string opaque type for IDs. Sometimes, I’m using a Js.Dict.t with an ID as key and it works well but !
I would like to enforce the type of the key as an opaque type for a better readability and avoid human mistakes.
module OrderId = MakeStringIdentifier();
type someDict = Js.Dict.t<string> // how enforce the OrderId.t as key ?
Should I go to something like Belt.Map.Dict or there is way to stay with the Js.Dict.t by creating an abstraction with a functor ?
Not sure Js.Dict supports something else for the key (out of the box), but you could use a Map, either from Belt or RescriptCore, e.g.
let orders: Map.t<OrderId.t, string> = Map.make()
orders->Map.set(OrderId.make("abc"), "Carrots")
or simply
let orders = Map.make()
orders->Map.set(OrderId.make("abc"), "Carrots")
orders->Map.get("abc") // Errors
If you’re using Belt, you could do something like this (using MutableMap for parity with Rescript Core’s Map)
module OrderIdComparable = Belt.Id.MakeComparableU({
type t = OrderId.t
let cmp = (a, b) => Pervasives.compare(OrderId.view(a), OrderId.view(b))
})
let orders = Belt.MutableMap.make(~id=module(OrderIdComparable))
orders->Belt.MutableMap.set(OrderId.make("abc"), "Carrots")
module type Id = () =>
{
type t
let make: string => t
module Dict: {
type key = t
type t<'a>
let get: (t<'a>, key) => option<'a>
@set_index
external set: (t<'a>, key, 'a) => unit = ""
@val
external keys: t<'a> => array<string> = "Object.keys"
@obj /** Returns an empty dictionary. */
external empty: unit => t<'a> = ""
let unsafeDeleteKey: (. t<string>, string) => unit
let entries: t<'a> => array<(key, 'a)>
let values: t<'a> => array<'a>
let fromList: list<(key, 'a)> => t<'a>
let fromArray: array<(key, 'a)> => t<'a>
let map: ((. 'a) => 'b, t<'a>) => t<'b>
}
}
module Id: Id = () => {
type t = string
let make = s => s
module Dict = Js.Dict
}
module MyId = Id()
let myId = MyId.make("foo")
let myIdDict = MyId.Dict.empty()
myIdDict->MyId.Dict.set(myId, "foovalue")
A Map seems great for most of the case !
I didn’t mention the need to store the Dict in the localStorage, so I tend to use Js.Dict.t to stay close to the object format.