I have heard a lot of people say any usage of typeid is bad design, yet to me it seems like it offers great utility.
I don't think anyone says that usage of typeid is itself bad design; rather, what you'll hear is that usage of typeid is indicative of bad design. The idea there is that any logic that distinguishes (say) Square from Circle should actually be in those classes, so should be expressed by a virtual function (polymorphism).
Needless to say, this is not an absolute rule.