6 ms·
Show HN: SuperUtilsPlus – A Modern Alternative to Lodash
Hey HN!
After years of wrestling with Lodash's quirks and bundle size issues, I decided to build something better. SuperUtilsPlus is my attempt at creating the utility library I wish existed.
What makes it different?
TypeScript-first approach: Unlike Lodash's retrofitted types, I built this from the ground up with TypeScript. The type inference actually works the way you'd expect it to.
Sensible defaults: Some of Lodash's decisions always bugged me. Like isObject([]) returning true - arrays aren't objects in my mental model. Or isNumber(NaN) being true when NaN literally stands for "Not a Number". I fixed these footguns.
Modern JavaScript: Built for ES2020+ with proper ESM support. No more weird CommonJS/ESM dance.
Actually tree-shakable: You can import from specific modules (super-utils/array, super-utils/object) for optimal bundling. Your users will thank you.
The best parts IMO:
compactNil() - removes only null/undefined, leaves falsy values like 0 and false alone
differenceDeep() - array difference with deep equality (surprisingly useful)
Better random utilities with randomUUID() and randomString()
debounce() that actually works how you expect with proper leading/trailing options
Also genuinely curious - what are your biggest pain points with utility libraries? Did I miss any must-have functions?
- deleted 1y ago[deleted]
- gaaaaaaaarf 1y agoNice work! Reminds me of https://github.com/angus-c/just https://github.com/angus-c/just Suggestion: add more tests and run some benchmarks
- dhax_or 1y agoThanks for this! I've already started adding more tests. I ran some benchmarks and they were really impressive. I will get it out in the next release
- addandsubtract 1y agoNot to be confused with the other Just: https://microsoft.github.io/just/ https://microsoft.github.io/just/
- latchkey 1y agoOr this https://github.com/casey/just https://github.com/casey/just
- Animux 1y ago[flagged]
- deleted 1y ago[deleted]
- dannyfritz07 1y agoI don't think we've really seen many successors to LoDash other than Ramda because the platform now has many of Underscore's functions built in.
- 7bit 1y ago> Like isObject([]) returning true - arrays aren't objects in my mental model. Correct me if I am wrong, but Array factually are JS objects and "[] instanceof Object" is true. Fair enough if that does not fit your mental model, but I would not use any library that treats facts like opinions.
- ivanjermakov 1y agoDistinction is tricky since you can use indexing on plain objects, e.g. const foo = {}; foo[0] = "bar";
- rafram 1y agoRight. For the purposes of standard library functions that operate on array-like objects, { length: 1, 0: "item" } is an array.
- williamdclt 1y agoI agree with the author that it’s almost never what you want. But I agree with you that it’s the reality of the platform, ignoring it will cause its own problems. I’d surface the footgun rather than trying to pretend it’s not there: isNonArrayObject and isObjectOrArray, or something like that
- 7bit 1y agoAbsolutely agree. I also hate that empty arrays are true, which is different from other languages. But I agree that it's better to face the reality of the language than create a function that evaluates [] to false. It trains you a bad habitnand some day that will cause you to introduce a bug.
- williamdclt 1y ago> I also hate that empty arrays are true, which is different from other languages I don’t mind that actually! I don’t think I have much use cases for “empty array is semantically different from non-empty”. Usually I find null/undefined are better choices, an empty array is just a normal array, I don’t expect it to be handled differently
- shy977954608 1y ago[dead]
- _1tan 1y agoWe use es-toolkit to replace Lodash - how would you compare your library? We just migrated a React app with around 500k LOC and this worked quite well and flawless.
- dhax_or 1y agoI've not used es-toolkit but from what I see you get lower bundle size, typescript support and a better performance with our library. I will be releasing the the benchmark soon enough so do watch the repository if you can
- uwemaurer 1y agoI use es-toolkit. It is fully in Typescript. Every function can be imported without any extra overhead, for simple functions it just adds a few bytes then to the bundle. I doubt "better performance" since most helpers functions are just tiny and there is no room for significant improvements. So I think trying to be better here is pointless, better focus on offering more helpful utility functions which might be missing in es-toolkit
- revskill 1y ago[flagged]
- deleted 1y ago[deleted]
- redslazer 1y agoWe migrated to remeda from Lodash and are pretty happy. https://remedajs.com/ https://remedajs.com/ What do you do differently?
- deleted 1y ago[deleted]
- jokull 1y agoI recommend https://remedajs.com/ https://remedajs.com/ - they're always making the types more accurate too. Like groupby has nonempty lists.
- gcmeplz 1y agoThe types look great on remeda, but one thing that looks intriguing about SuperUtilsPlus is the focus on being tree-shakeable. Lodash's lack of tree-shake-ability is a drawback to using lodash on the frontend. edit: the types on remeda look great though! If I were doing a backend-only NodeJS project, I'd be super tempted to test it out.
- bythreads 1y agoJust import what you use for lodash?, the theres not need for a treeshake situation?
- deleted 1y ago[deleted]
- deleted 1y ago[deleted]
- deleted 1y ago[deleted]
- yoz-y 1y agoWhat I’d like is a utility library like this, but instead of it being an actual library, be it some utility that generates a single file with exports of the few functions I need. Even just something that would make copy pasting them easier. As in, I want actual zero dependencies, not even the library itself. The reason: I never want these to randomly update.
- acbart 1y agoCouldn't you just pin a specific version dependency? My brain says there's some way to also pin to a hash, but that would require googling and I'm on mobile.
- nodewrangler 1y agoThe problem is that even if you pin to a version, at some point you’ll need to update node, typescript, or some other package, and then if this package doesn’t update, then you may have to migrate from it to something else. While js tries to enforce backwards compatibility, and npm, etc. help with the complex landscape, in practice with node, typescript, etc., even with LLMs helping, it can be a pita and hours or days of work to update at times. It’s just not worth it for things you could’ve just implemented yourself. There are exceptions to this, though.
- mystifyingpoi 1y ago> at some point you’ll need to update node, typescript, or some other package I experienced both sides of this discussion (project that always pulled :latest disregarding any kind of versioning, and project that had node_modules commited inside the repo) and both extremes suck, but I lean towards the second one. I'll totally take a few days of pain over not knowing whether prod will work today or not.
- hinkley 1y agoThis is why running your own mirror is what most large companies do. Guarantee no take-backs.
- 1y ago
- ryancnelson 1y agoBiggest pain point: wtf is lodash? I don’t care if it’s in your readme, but maybe tell us in your HN hype post
- cronelius 1y agolodash is extremely common knowledge in the js/web world. you’re asking a chemist to explain atoms before sharing their big discovery
- ryancnelson 1y agoNo I’m asking a commercial that pops up in what I’m watching and says “ask your doctor if ciallis is right for you.” and gives no context but someone washing their tesla.
- podgietaru 1y agoI don’t know. Maybe if it’s getting a lot of traction it’s beholden on you to look up what it is. I don’t understand everything on the HN frontpage either.
- nativeit 1y agoI dunno about anyone else, but someone washing their Tesla fits my mental model of impotence perfectly.
- robinson7d 1y agoDo the example functions (isObject, isNumber, differenceDeep, randomUUID, debounce), along with the name (“SuperUtilsPlus”), and sentences saying “utility library” and “JavaScript” really not give enough context to get an idea of what this library is for? And so if Lodash is what they’re trying to replace, is that not enough info to infer what Lodash might be? The pharma ad comparison seems more than a little hyperbolic to me.
- epolanski 1y agoTo use your analogy, this is more of "Show HN: Cialis - A modern alternative to Viagra". You either care about Viagra and read or move on.
- cronelius 1y agoI made twitter post 3 or 4 years ago making fun of Lodash team for _still_ not shipping loadash 5 and they didn't like it very much. They started working on Lodash 5 in like 2015 and it still hasn't shipped. Guess we make our own now
- deleted 1y ago[deleted]
- deleted 1y ago[deleted]
- insin 1y agoThe published version appears to be CommonJS only: $ node index.mjs import { isString } from 'super-utils-plus' ^^^^^^^^ SyntaxError: Named export 'isString' not found. The requested module 'super-utils-plus' is a CommonJS module, which may not support all module.exports as named exports. You might also need to update some of your type checks to handle wrapper objects like new String() - Object.prototype.toString.call(...) is your friend.
- rafram 1y ago> You might also need to update some of your type checks to handle wrapper objects like new String() There’s genuinely never a reason to use new String(). You should treat non-primitive String instances as bugs.
- the_sleaze_ 1y agoCan you explain a little? I've never heard this.
- rco8786 1y agoI wonder why the authors decided to make `flatten` only go one level deep, and have `flattenDeep` that goes N levels. AFAIK most other implementations of Array.flatten do it recursively through however many levels exist.
- meeech 1y agodon't discount the value of a good docs site. that was one of things i loved about lodash that made it so easy to use, and to discover all the functionality it offered. So if you looking to replace it, would be good to have similar docs.
- thih9 1y agoAbout pain points / feature requests: Is there an idiomatic way to duplicate a hash while replacing one of its values, preferably something that supports nesting? Whenever I work with react and immutable structures, this comes up and I hack something simple. I don’t do FE on a regular basis though so my perspective may be skewed.
- sethaurus 1y agoThese days that's pretty well-supported in the base language: const updated = { ...existing, someKey: someNewValue }; You mention nesting. That starts to look messier: const updated = { ...existing, someKey: { ...existing.someKey, ...someNewValue } }; There's a whole cottage industry of little libraries to make this ergonomic/fast in the general case (copying immutable objects with nested changes). `immer` is a popular choice. But the reality is that it gets complicated to do this generically; in my view it's usually better to just use the base language where possible, even if it means sprouting some util functions for the various kinds of updates you end up doing.
- antifa 1y agoThere might be a function called produce in one of your immutable/react lib.
- deadcoder0904 1y agohttps://radashi.js.org/ https://radashi.js.org/ is also a good alternative