Typed Arrays with PHPStan types

When dealing with legacy data, you often encounter arrays or associative arrays. These arrays are untyped, which PHPStan, of course, does not accept, resulting in numerous PHPStan errors.

PHPStan, by the way, is a static analysis tool for PHP that enforces strict typing and checks for compliance with PHPDoc annotations, ensuring code is robust and maintainable.
For any serious project you should use it.

For this code:

$array = $this->getUntypedArray();
$res = $this->funcWithInt($array['number']);
...
private function funcWithInt(int $number):int {
    return $number++;
}Code language: PHP (php)

A typical error could be:

Parameter #1 $number of method TestClass::funcWithInt expects int, mixed given.Code language: PHP (php)

You can try to typecast the value:

$res = $this->funcWithInt((int)$array['number']);Code language: PHP (php)

But PHPStan will not accept this and will yield this error:

Cannot cast mixed to int.

To type these untyped arrays, you can use PHPStan types. These types can be defined in a PHP DocBlock, and PHPStan will use them and the error will be gone.
You can also reuse the types throughout the code in this class.

Note that you need to define the PHPStan type in a DocBlock outside of the class.
If defined inside the class or in a function, it will not be recognized by PHPStan!

Example (see also here: https://phpstan.org/r/4ff8a134-4494-46e1-a026-1d5a741289e7):

<?php declare(strict_types = 1);

/**
 * @phpstan-type Test array{
 *     string: string,
 *     number: int,
 *     array?: array{title: string}
 * }
 */
class ExampleClass
{
    /**
     * @return Test
     */
    private function getArray(): array
    {
        return ['string' => 'test', 'number' => 42, 'array' => ['title' => 'title']];
    }

    public function processArray(): void
    {
        $array = $this->getArray();
        $res = $this->funcWithInt($array['number']);

	/** Test $anotherArray */
    	$anotherArray = ['string' => 'test2', 'number' => 66];
	$res = $this->funcWithInt($anotherArray['number']);
		
        echo "Result: " . $res;
    }

    private function funcWithInt(int $number): int
    {
        return $number + 1;
    }
}Code language: HTML, XML (xml)

Now the code will pass the PHPStan audit and some other benefits come with this:
PHPStan types are also supported beyond PHPStan.
IDEs like PhpStorm can recognize and use the type definitions.
Additionally, PHPStan types are compatible with Psalm (another static analysis tool which is often used in combination with PHPStan).

In general, I would say it is better to map arrays to typed objects, such as DTOs, but sometimes this is not practical, and in those cases, PHPStan types provide a quick way to type untyped data.