You don't "agree" on a convention, they have different use cases. Sometimes you'll want to merge a bunch of class names so you use array-style. Other times you have class names that have prop dependencies so you use object style and finally you'll want to merge in some always-on defaults so you have string style. You'll often need to combine them, depending on use-case.
That's a whole lot of complaints for 50 lines of code.
> There's some irony here -- all of this just to avoid dealing with string templates:
By that argument, we can just avoid everything by not making our apps dynamic!
> The classNames utility is a completely unnecessary abstraction.
The only necessary abstraction in programming is assembly since 0's and 1's are hard to reason about. The "need" in this case refers to needing to mix different primitives to make your app dynamic. Your arbitrary example above doesn't do anything because you still have conditional logic to determine what class1 class2 and class3 are, you are just doing a bunch of ugly crap in the render function rather than abstracting it. Or implementing your own version because you're smart.
It's a stupid hill to die on here... you want to argue about importing the entire lodash library because you like .chain, have at it. But I guess you can keep patting yourself on the back for avoiding importing a no-dependency 50-line library.
You want `undefined` and `null` to show up in class names? You'd at least need `${class1||''}` and your solution will grow in cases from there despite your one-liner.
Your solution doesn't do anything I'd expect someone wants that lib for, like merging in a map of classes.
I don't think this lib is the best pyre to die on to make a point I generally agree with.
That's a whole lot of complaints for 50 lines of code.