title: Best way to output strings based on conditionals logic
body: <p>I am looking for opinions on how best to achieve the following. Its purpose is from the backend to get a bunch of user configured data, and then based on that data configure an object of texts which will be used on the frontend. I want frontend to be dumb and just know that it has to display <code>text.string</code>. Backend will contain the logic of determining what is shown.</p>
  
  <p>I started with an object like this:</p>
  
  <pre><code>const someData = {
      hasBirthday: true,
      subscriptionFee: 100
  }
  
  const text = {
      welcome: (someData.hasBirthday) ? 'Happy birthday and welcome' : 'Welcome',
      cost: (someData.subscriptionFee &gt; 0) ? `Your subscription fee is ${someData.subscriptionFee}` : `Enjoy your free stuff`
  }
  </code></pre>
  
  <p>Fairly simple, however some additional logic was then introduced which was requiring nested ternary operators, so like this:</p>
  
  <pre><code>const someData = {
      hasBirthday: true,
      subscriptionFee: 100
  }
  
  const text = {
      welcome: (someData.hasBirthday) 
        ? 'Happy birthday and welcome' 
        : (someData.subscriptionFee &gt; 0) 
          ? 'Welcome' 
          : 'Welcome, some custom message about your account being free',
      cost: (someData.subscriptionFee &gt; 0) 
        ? `Your subscription fee is ${someData.subscriptionFee}` 
        : (someData.hasBirthday)
          ? `Enjoy your free stuff, you'll get a present on your birthday as well`
          : 'You only get free stuff, we do not know when your birthday is'
  }
  </code></pre>
  
  <p>To note this is just a subset example, of course I could do <code>if else</code> statements, The text is pretty much irrelevant but there to serve a purpose that it is drastically different for each combination of data comparisons.</p>
  
  <p>Now this got quite messy quite quickly, so I was wondering if anyone had thoughts on the following suggestion to keep things a little cleaner:</p>
  
  <pre><code>const texts = {
      welcome: [
          {
              comparator: (data) =&gt; data.hasBirthday,
              value: () =&gt; 'Happy birthday and welcome' 
          },
          {
              comparator: (data) =&gt; !data.hasBirthday &amp;&amp; someData.subscriptionFee &gt; 0,
              value: () =&gt; 'Welcome' 
          },
          {
              comparator: (data) =&gt; !data.hasBirthday &amp;&amp; someData.subscriptionFee &lt;= 0,
              value: () =&gt; 'Welcome, some custom message about your account being free'
          },       
          {
              comparator: (data) =&gt; true,
              value: () =&gt; 'This could act like an else conditional'
          },
      ],
      cost: [
          {
              comparator: (data) =&gt; data.subscriptionFee &gt; 0,
              value: (data) =&gt; `Your subscription fee is ${data.subscriptionFee}` 
          },
          {
              comparator: (data) =&gt; data.subscriptionFee &lt;= 0 &amp;&amp; someData.hasBirthday,
              value: () =&gt; `Enjoy your free stuff, you'll get a present on your birthday as well` 
          },
          {
              comparator: (data) =&gt; data.subscriptionFee &lt;= 0 &amp;&amp; !someData.hasBirthday,
              value: () =&gt; 'You only get free stuff, we do not know when your birthday is'
          },
      ]
  }
  
  // using lodash
  _.mapValues(texts, (text) =&gt; {
      const matched = _.find(text, (t) =&gt; t.comparator(someData));
      return (_.isFunction(_.get(matched, 'value'))) ? matched.value(someData) : null;
  }),
  </code></pre>
  
  <p>So now each value has a comparator function which can have various logic to define if it should be shown. _.find will search recursively in order so we know that the first to last take precedence. </p>
  
  <p>Anyway, looking for criticism on the above if anyone has any ideas. Thanks.</p>
  
  <h2>Updated: Builder Pattern Implementation</h2>
  
  <p>I am not building another class instance, just returning an object, but still the same idea:</p>
  
  <pre><code>class Builder {
    constructor(data) {
      this._data = data;
    }
  
    setWelcome() { 
      if (this._data.hasBirthday) {
        this.welcome = 'Happy birthday and welcome'
      } else if (this._data.subscriptionFee &gt; 0) {
        this.welcome = 'Welcome'
      } else {
        this.welcome = 'Welcome, some custom message about your account being free'
      }
      return this;
    }
  
    setCost () {
      if (this._data.subscriptionFee &gt; 0) {
        this.cost = `Your subscription fee is ${this._data.subscriptionFee}`
      } else if (this._data.hasBirthday) {
        this.cost = `Enjoy your free stuff, you'll get a present on your birthday as well`
      } else {
        this.cost = 'You only get free stuff, we do not know when your birthday is'
      }
      return this;
    }
  
    create() {
      return _.omit(this
        .setWelcome()
        .setCost(), '_data')
    }
  }
  
  const object = new Builder({
    hasBirthday: true,
    subscriptionFee: 100
  }).create();
  
  </code></pre>