DRYing a stateless functional builder
Found a solution and I think this is elegant, but I'm unsure if this is something that should be avoided or not since I'm fairly new to ES6.

Here are the following things I did to refactor it:


Unify the Builder signatures to use a single parameter product
Invoke the parent constructor within the child constructor with the same arguments on the instance.
Move the defaults into the build step of the Builder.
Use Object.assign to merge new properties.


There's a bit more that can be done to clean this up even further, but hopefully, this could be useful for someone else. One could repeat step 2 to include multiple Builders as well.



function ParticleBuilder(product) {
  MoveableBuilder.call(this, product);
  this.lifespan = (lifespan) =&gt;
    new this.constructor(Object.assign({}, product, {
      lifespan: lifespan
    }));

  this.decay = (decay) =&gt;
    new this.constructor(Object.assign({}, product, {
      decay: decay
    }));

  this.build = () =&gt; Object.assign({
      lifespan: 255,
      decay: 1
    },
    product);
};

function MoveableBuilder(product) {
  this.at = (...coordinates) =&gt;
    new this.constructor(Object.assign({}, product, {
      coordinates: coordinates
    }));

  this.facing = (...vector) =&gt;
    new this.constructor(Object.assign({}, product, {
      vector: vector
    }));

  this.build = () =&gt; Object.assign({
    coordinates: [],
    vector: []
  }, product);
}

console.info(new MoveableBuilder().at(1, 1).facing(2, 1).build());

console.info(new ParticleBuilder().at(1, 1).build());