rescript-webapi
rescript-webapi copied to clipboard
Switch property accessors to records-as-objects
Every property accessor in the entire project is an external. When bs-webapi was created that was the only way to do it. Since then records are compiled to objects so we can use (private) record types to represent the properties.
For example, DomRect:
type t = Dom.domRect;
[@bs.new] external make : (~x: float, ~y: float, ~width: float, ~height: float) => t = "DOMRect"; /* experimental */
[@bs.get] external top : t => float = "";
[@bs.get] external bottom : t => float = "";
[@bs.get] external left : t => float = "";
[@bs.get] external right : t => float = "";
[@bs.get] external height : t => float = "";
[@bs.get] external width : t => float = "";
[@bs.get] external x : t => float = "";
[@bs.get] external y : t => float = "";
Can now be implemented as:
type t =
pri {
top: float,
bottom: float,
left: float,
right: float,
height: float,
width: float,
x: float,
y: float,
};
[@bs.new] external make: (~x: float, ~y: float, ~width: float, ~height: float) => t = "DOMRect"; /* experimental */
This is still up for debate, because by not using the ReScript-provided abstract types like Dom.domRect
this will break compatibility with other DOM-related libraries. The improved ease of use is worth it in property-heavy types like DOMRect
, but perhaps it should be used sparingly.
by not using the ReScript-provided abstract types like
Dom.domRect
this will break compatibility with other DOM-related libraries
We could perhaps offer a toDomType
identity external on all types we do this with to convert the type back to the shared one. This would provide a compatibility option if necessary while we move towards more easy to use record types.
If this happens we'll need ofDomType
as well, integrating with other libraries is a two way street.
The pain of documenting this would be immense; I no longer think it's worth considering for 1.0.
Just occurred to me, what about doing the reverse as a potentially easier migration? e.g.
type t = Dom.domRect;
type internal_t =
pri {
top: float,
bottom: float,
left: float,
right: float,
height: float,
width: float,
x: float,
y: float,
}
external unwrap: t => internal_t = "%identity"
[@bs.new] external make : (~x: float, ~y: float, ~width: float, ~height: float) => t = "DOMRect"; /* experimental */
[@bs.get] external top : t => float = "";
[@bs.get] external bottom : t => float = "";
[@bs.get] external left : t => float = "";
[@bs.get] external right : t => float = "";
[@bs.get] external height : t => float = "";
[@bs.get] external width : t => float = "";
[@bs.get] external x : t => float = "";
[@bs.get] external y : t => float = "";
Yeah making custom types not the default reduces the impact, although it does reduce the usability a little, that's an interesting thought 🤔
Because of the record improvements in ReScript 11 doing this would also allow up-casting from HtmlDivElement.t
to HtmlElement.t
for example.
That is certainly a major advantage - but it depends on breaking away from the compiler types.
It's such a big change, the compatibility issues it would cause mean I'd want to get input from the compiler developers before I invest time in it.