Having lots of interfaces for common things is not a bad thing. See how Rust traits work... even basic structs you create will probably implement lots of basic traits (some of which can be done automatically, thankfully) like `Display`, `Default`, several `From` or `Into` impls, `Clone`, `Copy` if your type is "light", `AsRef`, `Send` and many more!
This makes code much more reusable as so many functions are written based on those basic traits alone.
Of course, finding the right basic types is really hard and your company seems to have done that badly, but in principle, having some basic types to model very common "things" is a necessary thing.
The issue isn't the interfaces; it's that there is only one implementation (the base classes) per interface—so why even bother having an interface? Otherwise, I agree with you to a degree.
The main issue with the codebase is that if you want to, say, change the behavior of a Book, you have to go change the behavior of some base class (after working out which one is actually being called). This base class might be used in a Clock, Field, or Filesystem as well—something so conceivably far away that their similar behavior is a coincidence and not really related at all. Then you get to argue with the architect about whether "reading a book" is different than "reading a clock."
This makes code much more reusable as so many functions are written based on those basic traits alone.
Of course, finding the right basic types is really hard and your company seems to have done that badly, but in principle, having some basic types to model very common "things" is a necessary thing.