[HN Gopher] Show HN: SuperUtilsPlus - A Modern Alternative to Lo...
       ___________________________________________________________________
        
       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?
        
       Author : dhax_or
       Score  : 75 points
       Date   : 2025-05-24 13:03 UTC (9 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | gaaaaaaaarf wrote:
       | Nice work! Reminds me of https://github.com/angus-c/just
       | 
       | Suggestion: add more tests and run some benchmarks
        
         | dhax_or wrote:
         | Thanks 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 wrote:
         | Not to be confused with the other Just:
         | https://microsoft.github.io/just/
        
       | dannyfritz07 wrote:
       | I 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 wrote:
       | > 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 wrote:
         | Distinction is tricky since you can use indexing on plain
         | objects, e.g.                   const foo = {};         foo[0]
         | = "bar";
        
         | williamdclt wrote:
         | I 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 wrote:
           | Absolutely 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 wrote:
             | > 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
        
               | 7bit wrote:
               | What do you think about empty strings being falsy in most
               | languages including js?
               | 
               | Null/undefined is a better choice, but there's many
               | occasions where you do not have the power of choice. For
               | example with document.querySelectorAll, which returns an
               | empty array if nothing is found. The simple thing to do
               | is to just check for it's length or just iterate over
               | it's nodes, but still. I prefer empty arrays being falsy.
               | 
               | Just to clarify, I'm not saying one is better than the
               | other. I just prefer how it works in other languages like
               | Python. But I still would rather work with the JS
               | language properties, than import a library that changes
               | how I test for empty arrays.
        
               | nothrabannosir wrote:
               | Akshually, implicitly casting any non Boolean type to
               | true or false is no better than implicitly casting "0" to
               | 0. :) B-)
        
               | 7bit wrote:
               | No better based on what criteria? In what language? This
               | is typical in Python and done even by core-devs. It is
               | how the language was designed and it was designed to
               | support that.
        
           | dcsan wrote:
           | your option is a bit more verbose but definitely more clear.
           | confusing the underlying definitions of the language itself
           | will lead to problems later.
        
             | PUSH_AX wrote:
             | Will it? Will it really?
             | 
             | I've been writing JS for so long I've forgotten all these
             | language quirks, I feel like it's fair for most people,
             | these language choices are kind of meaningless in day to
             | day, what's meaningful is a function returning things that
             | will make sense to most people. Or at least have two
             | functions, languageStrictIsObject()
        
         | bryanrasmussen wrote:
         | libraries of this sort, especially in JavaScript, often exist
         | to enforce a more reasonable mental model rather than the model
         | baked into the language.
        
           | 7bit wrote:
           | I understand that. I just don't think that it is a good
           | habit. Instead of just learning the languages and it's quirks
           | now you form a bad habit and start to rely on one dependency
           | for all your projects.
        
             | bryanrasmussen wrote:
             | this is generally the view I have on these sorts of things
             | as well, although I must admit that my views are often out
             | of step with what everybody else I work with feel on the
             | matter.
        
       | _1tan wrote:
       | We 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 wrote:
         | I'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 wrote:
           | I 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
        
       | redslazer wrote:
       | We migrated to remeda from Lodash and are pretty happy.
       | https://remedajs.com/
       | 
       | What do you do differently?
        
       | jokull wrote:
       | I recommend https://remedajs.com/ - they're always making the
       | types more accurate too. Like groupby has nonempty lists.
        
         | gcmeplz wrote:
         | The 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 wrote:
           | Just import what you use for lodash?, the theres not need for
           | a treeshake situation?
        
       | yoz-y wrote:
       | What 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 wrote:
         | Couldn'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 wrote:
           | The 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 wrote:
             | > 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 wrote:
           | This is why running your own mirror is what most large
           | companies do. Guarantee no take-backs.
        
           | mystifyingpoi wrote:
           | Pinning is a good strategy (I'd say that it should be the
           | default one), but depending on your level of paranoia (think
           | left-pad), you might consider just downloading the lib as it
           | is, and storing it in source control forever.
        
             | graypegg wrote:
             | I do sort of miss bower [0] for this reason. It was really
             | just a way to download javascript and plunk it into your
             | application. It was standard practice to check all of your
             | vendor dependencies into SCM. [1] Of course a good chunk of
             | it was transformed through something like Gulp or Grunt
             | before being added to the bower repository so you were
             | unlikely to maintain those once checked in, but there was
             | still quite a few packages (small jquery image gallery
             | plugins and the like) that were just some un-transformed
             | javascript someone typed up and threw at bower verbatim.
             | 
             | [0] https://bower.io
             | 
             | [1] https://addyosmani.com/blog/checking-in-front-end-
             | dependenci...
        
         | parentheses wrote:
         | OOC, what is the benefit of having a "library" that requires
         | such manual labor to maintain and upgrade?
         | 
         | You'd miss out on CVEs because you don't use the common
         | dependency paradigm.
         | 
         | You'd also miss out on bug fixes if you are not detecting the
         | bug itself.
         | 
         | Help me understand because I'm with you on less dependencies
         | but this does feel a bit extreme.
        
           | hofrogs wrote:
           | Why would small functions like "difference", "groupBy",
           | "flatten", etc. have CVEs and require bug fixes? Implementing
           | those correctly is a one and done thing
        
             | jsheard wrote:
             | You'd be surprised: https://positive.security/blog/lodash-
             | ramda-underscore-vulne...
        
               | hofrogs wrote:
               | Looks like these are mostly based on "reserved"
               | attributes (with double underscores that have no special
               | meaning in the language, just make unintentional
               | collisions less likely), a modern solution utilizing JS
               | Symbol type (where needed) would have no such issues
        
         | michaelsbradley wrote:
         | Why not copy & paste the code you need into a vendor/ subdir?
         | 
         | If the vendored code needs to be updated because of a change in
         | your build tools or whatever then you'll likely be making
         | similar changes to other parts of your project.
        
           | yoz-y wrote:
           | This is the approach I'm sometimes using, but it would be
           | nice to have tooling around that :)
        
         | fsloth wrote:
         | Nobody wants anything _ever_ to "randomly update". Why this is
         | the default setting on so many development setups boggles my
         | mind.
         | 
         | I really havent figured out why professional systems insist
         | running on the bleeding edge - it's your feet are bleeding here
         | I believe. 10 year ... 15 year old code is generally excellent
         | if you know it through and thorough.
        
           | skydhash wrote:
           | As my experience grows, I'm getting fonder of stances like
           | Debian or Common Lisp, which favors stability. Once you've
           | solved a problem, it's not fun having your foundation morphs
           | under you for no other reasons than bundling features and
           | security updates.
        
           | chrisweekly wrote:
           | CVEs are a thing. If vulnerabilities are discovered in your
           | dependency graph, choosing to ignore them can have severe
           | consequences.
        
         | programmarchy wrote:
         | shadcn distribution model for utils is a good idea. i wanted
         | something for react hooks as well and was surprised that didn't
         | seem to exist either.
        
       | ryancnelson wrote:
       | Biggest 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 wrote:
         | lodash is extremely common knowledge in the js/web world.
         | you're asking a chemist to explain atoms before sharing their
         | big discovery
        
           | ryancnelson wrote:
           | No 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 wrote:
             | I 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 wrote:
             | I dunno about anyone else, but someone washing their Tesla
             | fits my mental model of impotence perfectly.
        
             | robinson7d wrote:
             | Do 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.
        
         | AstroBen wrote:
         | Anyone who doesn't know what lodash is wouldn't be interested
         | in this. It's expected knowledge for the target audience
        
         | rgreek42 wrote:
         | Weird comment
        
       | cronelius wrote:
       | I 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
        
       | insin wrote:
       | The 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.
        
       | rco8786 wrote:
       | I 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 wrote:
       | don'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 wrote:
       | About 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.
        
       ___________________________________________________________________
       (page generated 2025-05-24 23:01 UTC)