Nothing built in, no. A CollectionProperty add() doesn’t even give you a name, it leaves it empty, and no dedupe happens at any point. The .001 suffix you’re used to belongs to ID datablocks in bpy.data, not to PropertyGroups.
So you do write it, but it’s short: an update callback on the name property that collects the sibling names, and if yours is taken, walks base.001, base.002 until one is free.
One thing worth knowing. Assign self.name inside that callback and it re-enters itself, which I measured at five invocations for three renames. Write self[“name”] instead and it’s three, because the raw key skips the callback. Same on 3.6 through 5.2.