PhpStorm 2021.1 Beta is now available. We are gradually adding generics support for PHP. Let’s get straight to it.
Support for Generics
Are there generics in PHP?
Generics via annotations
On the bright side, generics have been introduced in static analysis tools such as Psalm and PHPStan. Their adoption has grown quickly and many popular open-source PHP projects now rely on the generics annotations. So there is really no wonder why the `WI-47158 Generics support with @template` ticket is one of the most upvoted in the PhpStorm issue tracker.
We introduced support for Psalm and PHPStan in PhpStorm 2020.3. This support came with a basic “mirror” scenario for generics with the @template annotation. Read more about PhpStorm’s support for Psalm and PHPStan.
What will work in PhpStorm 2021.2?
Collections with @template
One of the most popular applications of generics is collections.
In PhpStorm 2021.2, you’ll be able to use generic class collections. Check out the Generics and why we need them post by Brent Roose to learn more about the advantages of such an approach over arrays.
In short, you get more bugproof code and better code completion.
Here is a simple example of the @template annotated collection class:
With the Doctrine Collections, you will already get a code-completion in simple scenarios:
Iterating over the Doctrine Collection interface does not currently work. Because to support this, two levels of template passing should be implemented: Doctrine Collection => IteratorAggregate.
So a workaround for this could be using a specific collection in the type hints, for example, ArrayCollection. With such annotation, you’ll be able to get code completion in a foreach loop:
Only first-level depth is supported
You can only get type inference and completion for first-level generics in PhpStorm, i.e. generics like Base<T> or Base<T1, T2>. For such annotations, PhpStorm will understand the T types.
Nested generics like Base<Child<T>> are not supported, and will likely not be supported in the future, because of the performance overhead.
Another application of generics is containers and factories. With such code, it is common to pass a class name string as an argument and receive an object as a result.
If you annotate some parameter with a @class-string<T> tag, PhpStorm will provide you with the appropriate type inference:
In fact, if you use the new operator to instantiate an object from a parameter, then there is no need to add a @class-string annotation – it’ll just work out of the box:
Basic cases for extending templated classes are also supported. For this, you can use @extends tag.
The @implements is supported but has a known issue when the template annotations form base signature are not inherited.
What is the future scope?
We are bringing the support for generics step-by-step. And plan to continue this work. There are a few known features missing that we’re planning to add in future updates:
WI-56034 Support generics on a class
WI-60894 Support parameter wrapping
WI-61438 Support inference based on IteratorAggregate
WI-61497 Generics template @implements should inherit annotations from interface
Feel free to create tickets if you find an uncovered case.
How do I submit feedback?
Please report any problems you find to our issue tracker or by commenting on this post.
You can also tweet us on Twitter by mentioning @phpstorm – we do read and respond to messages pretty quickly!
The full list of changes in this build is available in the release notes.
Your JetBrains PhpStorm team
The Drive to Develop