Skip to content

bs.deriving abstract: start with a record type or a creator function? #2680

Closed
@chenglou

Description

@chenglou

Here's an overview of bs.deriving abstract currently:

[@bs.deriving abstract]
type foo = {
  high: int,
  low: option(int),
};

This generates:

  • An abstract type t
  • A creator function: let foo: (~high: int, ~low: option(int)=?, unit) => t
  • Getters: high, low
  • Setters: highSet, highLow`
  • The original record type is erased
  • You can annotate the labels to make the creation function/getter/setter use a different name that's otherwise invalid, e.g. high(s) might compile to s["aria-high"].
  • Marking a record field as mutable generates the correct setter that mutates.

The goal is that we get some nice helpers, but also that it can generate platform-agnostic code. E.g. for JS backend, we can compile that abstract type to a JS object.

The other option is to start with a creator function:

[@bs.deriving abstract]
let foo = (~high: int, ~low: option(int)=?, unit) => "";

And generate the same helpers. This one has some advantages:

  • It's clear which labels are optional. Front-end might use a lot of optional args. In the current record-based deriving, if you write low: foo you wouldn't know whether foo is option(int) and accidentally make low non-optional.
  • You get to specify default values. This is limited, but nice.
  • You can customize the body of the function for future purposes.
  • The function name is customizable.
  • Likely less confusing for newcomers, because the first one has a record type which cannot be used (it's erased). So no weird errors when trying to create a value of that record type.

The drawback is that you for mutable field you'd need a new annotation.

I feel that the creation-based option might make more sense, but I'm not too sure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions