Well, your thread title does not make much sense. ECS is a buzzword in game development with no concrete definition. It just says that there are entities (also called game objects) which are composed of components. As such an ECS is a component based architecture. Furthermore, composing is the second programming idiom besides inheritance, and both are idioms of traditional OOP. Its just a fact that inheritance was overemphasized in many books and internet sites, so that composition was not recognized to the degree it should.
When you ask whether you should step away from composition and go with inheritance than think again. There is a reason why your trials in ECS world appear to be so smooth. Both composition and inheritance are tools, and you should use the right tool for the right problem.
Another thing to consider is the difference between code and data. It is much more elegant to make differences in game objects by parametrization (i.e. giving them different data) instead of inheriting another class. For example, the look of a spell is a different set of animation data and its damage is just a different value. So there is no need to make a Spell base class and inherit a FireBolt and an IceBolt class from it; the base class is sufficient (in this example; of course, situations may arise where having 1 or 2 inheritance levels would be okay).
The existence of "systems" to handle the components is a step that makes the management of all of the components easier. This is because an entity's components can be registered with the belonging systems when the entity is instantiated and added to the game world. Notice that components, although named commonly so, are ver different in their meaning (e.g. a Placement component and a SpellSpawner component). Due to their inherent differences, it is not logical to manage them the same way. If there are systems to manage them, then each system can be implemented in its own optimal way.
So, for me, going that way has no real alternative if you plan to do something more complex, especially if you don't want to re-program for each single game design decision. Of course, a small and isolated example like your scenario can be implemented in any other way, too.