phpstan / phpstan-webmozart-assert

PHPStan extension for webmozart/assert
160 stars 27 forks source link

`Assert::isInstanceOf*()` does not work with generics #183

Closed axlon closed 1 day ago

axlon commented 3 days ago

I've noticed that the instanceOf assertions do not work with generics. Looking at the extension's code it makes sense; we don't know the type of T yet so we can't tell PHPStan what the type is going to be. We do however know that $value is an object, so some narrowing should be possible.

/**
 * @template T of object
 */
final class Example
{
    /**
     * @param non-empty-array<non-empty-string, class-string<T>> $classMap
     * @param class-string<T> $className
     */
    public function __construct(
        private array $classMap,
        private string $className,
    ) {
    }

    public function example(mixed $value): void
    {
        \PHPStan\Testing\assertType('mixed', $value);
        Assert::isInstanceOf($value, $this->className);
        \PHPStan\Testing\assertType('object', $value);
        Assert::isInstanceOfAny($value, $this->classMap);
        \PHPStan\Testing\assertType('object', $value);
    }
}

Expected:

Actual output:

 ------ ------------------------------------- 
  Line   src/Example.php                      
 ------ ------------------------------------- 
  29     Expected type object, actual: mixed  
  31     Expected type object, actual: mixed  
 ------ -------------------------------------