Syntax sugar for turning a Js record into several sum types

interop

#1

Hello,

I’m on a situation where I have a javascript object. The shape, albeit complex because all the posible null types is known beforehand (or at least the expected shape!)
This object represents command line arguments where some fields represent a flag, others are a command and other are arguments to those flags/commands.
In order to better interact with them from reason I want to turn all the possible states represented by the record to sum types representing the possible actions and their arguments.

Currently, the only thing I have is a nested (and ugly !) if else expression that reads like this:

let parse = str => {
  let args = D.parse(str)
  Js.log(args);
  if (upgradeGet(args)) {
    Upgrade(stackNameGet(args), "pene");
  } else if (upgradeFinishGet(args)) {
    FinishUpgrade(stackNameGet(args), readName(args));
  } else if (configGet(args)) {
    Config(saveEnvGet(args) ? SaveEnv : Print);
  } else if (args->versionGet) {
    Version;
  } else if (getGet(args)) {
    Get(
      dockerComposeGet(args) ? DockerCompose : RancherCompose,
      stackNameGet(args),
      args -> outputGet ? Name(args->fileNameGet) : NoFile
    );
  } else {
    Invalid;
  };
};

All those xxxGet(args) things that you see repeated over and over again are just object property access. those accessor functions are generated from a record I defined deriving abstract. I need to derive abstract instead of jsConverter (which would be much more easier to work with) because I need to rename some fields.

Is there a better way to this ? Something like with args or stuff like that ? Any suggestion is more than welcome


#2

Some user at the discord channel (lorenzo_pomili) has suggested this

  switch (args) {
  | args when args->upgradeGet =>
    Upgrade(stackNameGet(args), args->imageNameGet)
  | args when args->upgradeFinishGet =>
    FinishUpgrade(stackNameGet(args), readName(args))
  | args when args->configGet => Config(saveEnvGet(args) ? SaveEnv : Print)
  | args when args->versionGet => Version
  | args when args->getGet =>
    Get(
      dockerComposeGet(args) ? DockerCompose : RancherCompose,
      stackNameGet(args),
      args->outputGet ? Name(args->fileNameGet) : NoFile,
    )
  | _ => Invalid
  };

While being much more readable, it is still a lot of repetitive code.
Still looking for alternatives