phptypesphpdocpsalm-php

How To Declare Traversable Type?


There are multiple typehints in PHP, more now in PHP 8, and even more with Psalm. But what about declaring the type, rather than hinting the expected type?

I have a interface Collection extends Traversable, and I need to declare that it is a traversable of type Abc. How can I do that, so that PHPDoc or Psalm know that when I iterate over instances of my Collection, each element will be of type Abc?

In other words, I need to, on interface level, guarantee that the assertion will always pass:

function doWithItems(Collection $items): void
{
    foreach ($items as $item) {
        assert($item instanceof Abc);
    }
}

Solution

  • I don't have a working interface example in my code (and these can be tricky to get right), but since Psalm implements interface Traversable<TKey, TValue> template on Traversable it would be something like:

    /**
     * @extends Traversable<array-key,Abc>
     */
    interface Collection extends Traversable
    

    A definitely working class-level example from my code using Doctrine Collections (which has very thorough Psalm support, you can look through source for how they do it):

    /**
     * @extends ArrayCollection<array-key, ShowInterface>
     */
    final class Shows extends ArrayCollection