Lodash is dead. Long live Radash.

Ray Epps
Exobase
Published in
7 min readAug 23, 2022

Lodash is old and lame, Radash is new and kool. What more do you need to know?

What’s wrong with Lodash?

In a time when Javascript’s dynamic abilities were held as a feature instead of a bug, Lodash was made to be as helpful as possible by providing functions that behave differently given different inputs. These days, we know better. Functional concepts like pure functions, deterministic behavior, and function composition have taken root in the javascript community — thank god 🙏

Lodash was created in 2009 (as Underscore) and rose to power after a fork (as Lodash) around 2012–2013. Do you remember Javascript circa 2012? At that time, I believed writing a backend in Javascript was irresponsible and foolish. The language was too unsafe, unmaintainable, and unwieldy. It’s a bit astonishing to think how far the language, runtimes, and community have all come in 10 years. It is not the same.

Lodash was designed and developed to solve Javascript developers' problems circa 2012. Those aren’t our problems anymore. The addition of optional chaining and null coalescing alone makes a large handful of Lodash functions obsolete. Not to mention the changes since the rise of Typescript. In today's market, a package as foundational as Lodash must provide helpful types.

A Function Breakdown

So you don’t think I’m just blowing smoke, I’ll walk through some of the Lodash functions and why they belong in a museum and not in your project.

Lodash’s _.get function

The _.get function allows you to pass a string or array value to the path parameter. This was considered a dynamic feature back in the day but we should all know now it’s just a bug waiting to happen now. In Typescript the code _.get({ name: 'ray' }, 'age') won’t produce an error because Lodash’s types don’t verify the given string path exists in the object.

Lodash’s _.filter function

There are three issues here.

  1. The function accepts different types as the second parameter. Again, no longer a feature.
  2. When passing an object, array, or string the types don’t work. Because of Lodash’s poor typing, Typescript can’t check if the values passed exist on the types of the provided array.
  3. Because of nullish coalescing and optional chaining, thefilter function is a bit obsolete. It was helpful when null checking needed many lines of code to do safely but any of the examples in the image above can now be written with ? and ?? just as same and just as short.

I won’t drag on these same topics but these points apply to many other functions as well. The _.find and _.some functions are just two examples.

Lodash’s _.map function

Even more egregious are functions like _.map and _.size. They have all the issues mentioned above as well as the ability to accept a variety of values as the first and second parameters. Not a feature!

Code Quality

I could accept everything talked about so far but this is really where I draw the line. If I’m using a small helpful toolbelt library with functions I could easily implement myself — they’re not that hard to write— I should expect that I can easily look at the source code.

Here’s a link to the source code that the Lodash docs link to. Take a look.

There was a time when I was younger when I would have spent hours digging through the source, learning every internal API, cataloging every function call, and eventually understanding it well enough to answer a simple question like how does the isNumber function work?

I should not have to sift through 15,000 lines of code and learn internal APIs to understand how a one-liner function works. This is the anti-pattern of all anti-patterns.

I understand why this is the reality. If you are traditionally educated as an engineer you’re taught to be DRY above all else. If you’re not in the cult and haven’t drank the Kool-Aid you might know that there are things more valuable than DRY code. In some cases attributes like readability, maintainability, testability, and not pissing off your tech lead are only possible by repeating yourself.

Like anything, it’s a balance. Lodash, as a simple toolkit library, has gone off the deep end with its code base.

But that Community Though…

This is the one strength of Lodash. It’s old, everyone knows it, and StackOverflow is full of QA about it.

Also, to its credit, it was critically helpful to a previous generation.

What Then?

Radash, pronounced /raw-dash/ (Ramda + Lodash), is the Lodash of our generation.

  • It’s a zero-dependency Javascript utility toolkit built in this decade.
  • It’s written in Typescript so strong, and useful, types come prepackaged.
  • It omits the functions that have become obsolete in Lodash over the years
  • It provides new functions you’ve never seen before but always wanted (see below)
  • The source code is maintained with understandability for newcomers as a top priority. In most cases, if you want to use a Radash function but don’t want to install it you should be able to copy it straight from GitHub.
The try function

The try function is probably my favorite Radash function. It’s the biggest hack to code cleanliness I’ve found in the last 10 years. No more forking the control flow when you want to try something. No more creating a mutable let variable outside the try, setting it inside, and checking it after.

As always with Radash, you’ll love the source and how strong the types are.

The parallel function

The parallel function has become my drop-in replacement for Promise.all . I know a team who has completely replaced the use of Bluebird in their project with parallel. Not only can you control how many requests are made at once but the error handling is far better. The parallel function throws an AggregateError with all child errors inside after all promises have resolved. This means the response from parallel isn’t an awkward array of objects with an error and value property, it’s just the values you want and expect.

Check out the source.

The retry function

The retry function has become a replacement for the async-retry library for me and my team. Combine try, parallel, and retry and you have the tools to replace most backend service fault tolerance libraries out there.

Check out the source.

The counting function

The counting function counts the occurrences of keys or identities in an array. It’s one of those small functions you find yourself using more than you expected.

Check out the source.

The range function

The range function is incredibly helpful when dealing with loops. When I see a raw for (let i; i < n; i++) loop I tend to throw up in my mouth a little. The range makes the same kind of function so easy and simple that you can get the same behavior without of the smelly code and risk.

Range returns a generator so you can safely call range(0, 100000000)

See the source.

The list function

The list function is the range function’s beautiful cousin. In some cases, you need a real list, not a generator. In those cases, you have the list function. Easy, quick, and dynamic list creation is also useful in a lot of use cases outside of looping.

See the source.

There are so many more amazing functions. Here are a few more of my favorites.

All functions are well-typed, well-documented, well-tested, and written with simplicity as a priority. If you find that I’m wrong please submit a PR or open an issue!

The one thing Radash is missing that Lodash has is the community. If you like Radash, share this article, star it on GitHub or share it with a friend.

I wrote and maintain Radash. This changes nothing.
- Ray

--

--