DEV Community

Discussion on: The Case for TS+

Collapse
mikearnaldi profile image
Michael Arnaldi Author

What can you do of the above with vanilla JS? Derive runtime codecs? have tree-shakable fluent APIs?

Collapse
jfbrennan profile image
Jordan Brennan

Sorry, not super familiar with FP, but seems like the same benefits and fluent API can and have been achieved with vanilla JS for more than a decade (e.g. jQuery, Underscore/Lodash, many others). Are you saying tree-shaking is not as effective?

Thread Thread
mikearnaldi profile image
Michael Arnaldi Author

Lodash/Underscore are not Fluent APIs they are just modules of functions that is ok, there is a usability compromise though take for example an array "a" to map "a" you do "a.map(f)" doing "map(a, f)" isn't as nice, nor doing "pipe(a, map(f))", jQuery has a fluent api but that sort of comes from a different era and nobody is tree shaking jq. Fluent APIs cannot be tree-shaken (at all), class methods cannot be removed nor renamed, libraries like fp-ts or rx-js have moved away from those API because they aren't shakable and they aren't extensible (i.e. adding a method to a class coming from a library)

Thread Thread
jfbrennan profile image
Jordan Brennan

Curious, why would a functional programmer not want to say this counts as a fluent API:

_.chain(lyrics)
  .map(line => line.words.split(' '))
  .flatten()
  .reduce((counts, word) => {
    counts[word] = (counts[word] || 0) + 1;
    return counts;
  }, {})
  .value()
Enter fullscreen mode Exit fullscreen mode

My understanding is chaining = fluent.

Thread Thread
jfbrennan profile image
Jordan Brennan

...and importing those functions (instead of using _) makes the code tree-shakable, right?

Thread Thread
mikearnaldi profile image
Michael Arnaldi Author

Yeah, incorporating those functions (map/flatten/etc) you end up with all, for effect that can be huge there are modules with 1000+ functions

Thread Thread
patroza profile image
Patrick Roza • Edited on

@jfbrennan importing individually gains tree shaking but would mean losing chaining/fluent and therefore discoverability and usage context.

reduce(flatten(map(lyrics, line => line.words.split(' '))), (counts, word) => {
    counts[word] = (counts[word] || 0) + 1;
    return counts;
  }, {})
Enter fullscreen mode Exit fullscreen mode

or piped

pipe(
  lyrics,
  map(line => line.words.split(' ')),
  flatten,
  reduce((counts, word) => {
    counts[word] = (counts[word] || 0) + 1;
    return counts;
  }, {})
)
Enter fullscreen mode Exit fullscreen mode

With ts+ you keep chaining/fluent, discoverability and usage context, while it gets compiled down to individual imports for tree shakability and optimisations. win-win.
The bigger the library (or the more libraries), with the more type classes/modules, the more the win is.