DEV Community

Discussion on: Four Ways to Immutability in JavaScript

Collapse
 
latobibor profile image
András Tóth • Edited

Great write-up to illustrate the problems and solutions of immutability! I have a couple of remarks:

  • I loved immer's approach since it was the cleanest.
  • I think immutable.js passed away silently: the last release was 14 months ago and it also has problems with TypeScript which does not seem to be ever solved.
  • Finally I have serious problems with Ramda's syntax; personally I think it is a horrible API from the point of clean code:
// Any function that relies on you memorizing the order of parameters 
// will make you do unnecessary doc checks. 
// If you don't use `R.set` for 2 days then any of these would look legit:
R.set(frns0pets0name, 'Spot', dino);
R.set('Spot', frns0pets0name, dino);
R.set(dino, 'Spot', frns0pets0name);

// An alternative to this could be this:
R.set({ source: dino, lens: frns0pets0name, value: 'Spot' });

// another problem: stringly typed; if you were relying on TypeScript
// for example it won't save you, it won't know the difference between
// any string and a string coinciding to be a property name
immDino.getIn(['friends', 0, 'pets', 0, 'name'])

// one day someone will rename `name` to `firstName` using a tool in their IDE,
// the tool will find all Dino objects, and update them; except these string ones
Enter fullscreen mode Exit fullscreen mode

So the take-away: use the cleanest, most intuitive ones until you have a performance bottleneck; then use the complicated ones for those cases.

Collapse
 
glebec profile image
Gabriel Lebec • Edited

You make a very good point about Ramda. This generally isn't a problem in Haskell (one of the inspirations for Ramda) because of static typing, which enforces that a function like set takes a lens, source object, and target value in the correct argument order (else it simply won't compile). Then, the fact that set is curried allows for a lot of seamless interop and versatile usage patterns with other higher-order functions. In JS however, the lack of HS-style flexible/powerful static typing means you have more opportunities to make mistakes, passing the wrong object into the wrong argument position. Ramda still provides some very flexible usage patterns due to currying, but I don't demonstrate or highlight those techniques in this article as they fit into a much wider topic of FP approaches.

Likewise, I agree with you about the problems of "stringly-typed" APIs. Again in Haskell this isn't an issue for lenses for a variety of reasons, including the fact that lenses can be auto-generated from record field names and composed using the vanilla function composition operator (.) so you end up with lines like friends . first . pet . name which is 100% typed, non-string code.

The moral may be that trying to emulate Haskell in JavaScript can look almost as nice in a purely syntactic sense, but lose so many of the real benefits that it becomes correspondingly harder to justify the exercise.