I use @extends and generic feature:
/**
* @extends AbstractCollection<ServiceInterface>
*/
class Services extends AbstractCollection
{
}
/**
* @property-read \PhpCliShell\Application\Firewall\Definition\ObjectDef $definition
* @property-read int $length
*
* @template O of AbstractApi
* @implements CollectionInterface<O>
*/
abstract class AbstractCollection implements
CollectionInterface,
ArrayAccess,
IteratorAggregate,
Countable,
Stringable
{
/**
* @var \PhpCliShell\Application\Firewall\Core\Api\AbstractApi[]|O[]
*/
protected array $_store = [];
}