Skip to content

Looking for a best practice to suggest a type for PHPStorm (safely) #3826

Closed
@enumag

Description

@enumag

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions