Mapping a user's availabilities
Another variant of the code

I took your second (more functional) example and polished it a bit.

*) The const keyword is used instead of the let in two places. This prevents accidental/undesired re-assignment of a value to a local variable.

**) the type of the accumulatorMap and key can be inferred.

***) The .reduce() is simplified, since map.set(key, value) already returns you a map object.

getMyAvailabilities(startDate: Moment, endDate: Moment): Observable&lt;Map&lt;Moment, Availability&gt;&gt;
{
  const params = new URLSearchParams();                              // *
  params.set('startDate', startDate.format(this.formatDateString));
  params.set('endDate', endDate.format(this.formatDateString));

  return this.http
    .get(this.resourceUrl, { search: params })
    .map((response: Response) =&gt; {
      const result = response.json();                                // *
      return Object.keys(result)
        .reduce(
          (accumulatorMap, key) =&gt;                                   // **
            accumulatorMap.set(moment(key), result[key]),            // ***
          new Map&lt;Moment, Availability&gt;()
        );
    });
}


Functional vs imperative — hopefully not off topic

Disclaimer

I don't think that Codereview.StackExchange is the right place to ask questions of that sort. The answers may get extremely subjective (and result in a "holy war"). The issue is that there's no universally objective criteria which could be used to justify that functional code is by definition better than imperative ...or vice versa.

I prefer functional...

Still, I chose the functional code snippet you provided and improved it, rather than the imperative. Here's the reason why, but please take it as an opinion.

In my experience, functional code is less buggy, so to speak. Now, I do not have any data to back this statement, and my guess is that the scientific studies on that subject are contradictory. Nevertheless, this is what I feel about it.

Reasoning behind "functional is better"

Here are a very few functional programming aspects and their possible effects:


Working with Maybe/Option [monad] makes the code more generalized, gets rid of explicit branching —> Simpler code. —> Defect likelihood reduces.
Using const instead of let or var prevents accidental object reassignment. No if-guards are needed. —> Defect likelihood reduces.
Pure functions do not modify the state, nor alter the input parameters, and always return same results for same inputs. —> Simpler code. —> Defect likelihood reduces.
...
I think you get my point but please do not trust me! Search online for more in-depth articles or blog posts. :)


Psychology matters

However, as you said, it takes time to adjust one's mindset, way of thinking, or habits — call it whatever you want — to harness functional programming aspects.

Remember how you touched a declarative (e.g. SQL), logic (e.g. Prolog), functional (e.g. Haskell, Lisp, Scala) or any other fundamental paradigm language for the first time. I bet it was not easy to grasp. For the first several weeks or months everyone in this position will write a lot of imperfect code and it's totally fine (as long as he/she is willing to revisit and fix it).

During this period the code may be more buggy, but this effect is temporary and diminishes with experience and learning time investments. It is important from the psychological standpoint to not make any conclusions at this point about whether the paradigm being adopted is good or bad. For the same reasons, it's extremely important to not judge a dev nor his code too strictly.

Anesthesia?

If you agree that the benefits are sweet, you want to push for functional code when possible. Still, the transition process may be painful. What do you do?

Well, here're the good news. The Divide and Conquer principle can be successfully applied. In fact, this is how I learn functional programming myself. You don't need to learn all the aspects at once (just like the SOLID principles, or design patterns).


Add one tool at a time to your toolkit and start harvesting the fruits.
Polish your skills over time and they become your second nature.
Experiment with what you've learnt.
Keep investing into the tools (in other words, make sure point 1. is repeated).
Retrospect and notice how the practices/aspects can be efficiently combined together. Often the case it happens intuitively without intentional search for it.
Be patient...
PROFIT!


P.S.

Many programming languages that have functional traits don't push a developer very hard towards writing functional code. This is especially true for the languages that acquired these traits as a result of evolution (like C# and latest versions of Java). Developers can still write imperative code even in Scala, the language does not prevent that.

Obviously, there's no silver bullet in programming. There will always be bugs out there, no matter what king of programming language we're talking about. It's the human beings who write the code, and we are not perfect in it. Realistic expectations may help a lot to achieve satisfaction instead of disappointment.