Earlier quoted context omitted.
Okay. Find an equivalently surprising example in... Let's use the other poster's choice, python. I'll wait. Edit: didn't have to wait long, way to go Python! Maybe I'll just claim it probably has fewer of these types of bizarre idiosyncrasies? I hope it has fewer... I'm always baffled by JavaScript apologists... Look, your baby is ugly. We know it's ugly. You know it's ugly. But if we point out the problems, hey, may…
I find this behavior surprising: >>> d = {0: "int"} >>> d[False] = "bool" >>> d {0: 'bool'} >>> nan = float('nan') >>> d[nan] = 0 >>> d[nan] = 1 >>> d {0: 'bool', nan: 0, nan: 1} Yes, yes, it's because issubclass(bool, int) == True, and nan != nan, but weird. And if we include Python 2 you get the truly ridiculous: >>> dict() >> dict >> 0 >> 0 To compare e.g. a dictionary and set we compare the _names_ of the types!…
> Personally I'd just make any comparison involving different types an error
As you point out, this is what Python 3 did for `None`. But it's been idiomatic to have 0 = False when languages didn't have `False`; so `bool(0) == False` makes sense, but also `sum(boolean for boolean in sequence)` works. So you could argue that for `True` and `False`, meaningful coercion is possible, and in reverse, if zero is false-y and everything else is truth-y (like in C), then that also makes sense. Imagine if you had to cast every number to a boolean explicitly! So I guess having `d[0] == d[False]` is the lesser of evils.