I'm using generics to type hint some classes and interfaces in php/phpstan. What i want to achieve is that a function returns a an interface object but with generic hinting:
class Car
{
}
/**
* @template S of object
*/
interface BuilderInterface
{
/**
* @return S
*/
public function build(): object;
}
/**
* @implements BuilderInterface<Car>
*/
class CarBuilder implements BuilderInterface
{
public function build(): object
{
return new Car();
}
public function notAnInterfaceFunc(): void
{
}
}
/**
* @template T of BuilderInterface
* @param class-string<T> $builderClass
* @return T
*/
function createBuilder(string $builderClass): BuilderInterface
{
return new $builderClass();
}
/**
* @template T of BuilderInterface
* @param class-string<T> $builderClass
* @return BuilderInterface
*/
function createBuilder1(string $builderClass): BuilderInterface
{
return new $builderClass();
}
$builder = createBuilder(CarBuilder::class);
\PHPStan\dumpType($builder->build()); // proper return object is of type Car
$builder->notAnInterfaceFunc(); // the function is callable
$builder1 = createBuilder1(CarBuilder::class);
\PHPStan\dumpType($builder1->build()); // return object is 'object'
$builder1->notAnInterfaceFunc(); // is not callable
Take a look at both createBuilder() functions. The second one acts like i want and returns an interface of CarBuilder::class, but it's doesn't properly sets the generic type for the CarBuilder class.
What i want:
$builder->build()returns an object of typeCarnotAnInterfaceFunc()is not callbable
I've made a phpstan pastebin, so you can play around with the code: https://phpstan.org/r/3fa3c78c-fff1-4590-8778-51e7475c470a.