Proper type hinting for IteratorAggregate satisfying Psalm and PhpStorm

256 views Asked by At

I have collections using IteratorAggregate interface. And I can't find a way how to type hint it properly that both Psalm and PhpStorm are satisfied.

Here is a simplified example. It has an AbstractCollection and one Collection, but there are actually multiple collections extending the AbstractCollection. This example works fine for PhpStorm but Psalm complains about it.

https://psalm.dev/r/9a3fc1db43

I tried several things, but nothing really works. Any ideas how I can get proper type hinting in PhpStorm when iterating the collection, but at the same time have Psalm not complaining?

1

There are 1 answers

1
weirdan On

This should work: https://psalm.dev/r/24c1344df3

<?php

/**
 * @template TValue
 * @template-implements IteratorAggregate<string, TValue>
 */
abstract class AbstractCollection implements IteratorAggregate 
{
    /**
     * @var array<string, TValue>
     */
    protected array $items = [];
    
    /** @return ArrayIterator<string, TValue> */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->items);
    }
}

/**
 * @template-extends AbstractCollection<string>
 */
class Collection extends AbstractCollection 
{
    public function __construct() {
        $this->items = ['foo' => 'bar'];
    }
}

foreach (new Collection() as $item) {
    echo $item; // PHPStorm should know the type here
}

You missed the docblock on AbstractCollection::getIterator().