Omit attribute from record type

Is this possible?

type test = {
  attr1: option<string>,
  attr2: string
}

// I would like to omit `attr1`
// but Rescript forces me to write `attr1: None`
let aaa: test = {
  attr2: "I'm mr. Meeseeks. Look at me!"
}
type test
@obj external createTest: (~attr1: string=?, ~attr2: string, unit) => test = ""

let aaa = createTest(~attr2="I'm mr. Meeseeks. Look at me!",())

compiles to

var aaa = {
  attr2: "I'm mr. Meeseeks. Look at me!"
};

Edit: Or with a more familiar structure


module Test =  {
  type t
  @obj external make: (~attr1: string=?, ~attr2: string, unit) => test = ""
}

let aaa = Test.make(~attr2="I'm mr. Meeseeks. Look at me!", ())

That’s kinda what @deriving(abstract) is doing as well, but it also introduces a lot more functionality than one would actually need:

module Test = {
  @deriving(abstract)
  type t = {
    @optional attr1: string,
    attr2: string
  }
}

let aaa = Test.t(~attr2="I'm mr. Meeseeks. Look at me!",())
3 Likes

You can also write a constructor function for your type:

let make = (~attr1=?, ~attr2, ()) => {
  attr1: ?attr1,
  attr2: attr2,
};

let test = make(~attr2="", ());

The ?attr1 passes the argument as an optional value. The () is needed because the compiler requires a final positional argument to be able to understand when all named arguments have been passed in.

This will produce a value: {attr1: None, attr2: ""}.

4 Likes

Ever since records as objects was released I’ve often pondered whether to request a way for records with optional fields to omit keys when the value is None. Records are a much nicer way to write bindings than @deriving and @obj, those feel clunky now, but I’m forced to use them when undefined values must be omitted.

3 Likes

couldn’t this be done at a syntax level in rescript?

1 Like

Do you have an example of “at the syntax level”?

I was thinking something similar to how @deriving(abstract) works, rather than syntax, since omitting optional fields would need to happen at multiple levels of the compiler.

For example:

@omitOptions
type myRecord = {
  attr1: int,
  attr2: option<string>,
  attr3: int
};

let value = {
  attr1: 5,
  attr2: None,
  attr3: 6
};

This would then omit attr2 in JS:

var value = {
  attr1: 5,
  attr3: 6
};

value.attr2 will return undefined whether or not the key was defined, so the runtime behaviour should be the same.

no sorry my bad, you would definitely need the type information too, not doable purely on a syntax level.

This was discussed in this issue: