Description
I think anyone who uses PHPStan with strict rules and such is familiar with this problem:
/**
* @param Traversable<DateTime> $dates
*/
function test(Traversable $dates): void
{
foreach ($dates as $date) {
// Here PHPStorm doesn't know that $date is instanceof DateTime and doesn't suggest anything.
}
}
Unfortunately I was unable to find a good way to tell PHPStorm what the type is:
Solution 1 - @var annotation
The first usual solution to this is to add a @var annotation like this:
/**
* @param Traversable<DateTime> $dates
*/
function test(Traversable $dates): void
{
/** @var DateTime $date */
foreach ($dates as $date) {
// Now PHPStorm knows the type.
}
}
The problem with this approach is that PHPStan trusts these annotations blindly. After some refactoring I had some cases where the annotations were completely wrong, the code didn't work but none of my static analysis tools reported a problem.
Of course if PHPStan compared the TValue from the Traversable against the annotation type it would find out there is a mismatch immediately.
So I what I'm looking for is a syntax that would tell the type to PHPStorm and which PHPStan would verify to be correct without trusting it.
Solution 2 - assert function
Another solution is the assert function:
/**
* @param Traversable<DateTime> $dates
*/
function test(Traversable $dates): void
{
foreach ($dates as $date) {
assert($date instanceof DateTime);
// Now PHPStorm knows the type.
}
}
This syntax tells PHPStorm about the type and PHPStan verifies it.
The problem is that PHPStan's strict rules report the instanceof as always true and the assert as useless. Which is true but I still need the assert there for PHPStorm. And of course I don't want to disable the rules that report this completely because they're very useful to check if (...)
statements and such.
Do you have a better solution? I assume there is none at the moment. Would you consider some changes to PHPStan to make this possible?