I feel stupid asking such a simple question, but I am clearly missing something basic.
The CollectionOrdered class below is meant to "carry a payload" and the point of HasPayloadInterface is to encapsulate operations for all classes which carry a payload, not just CollectionOrdered.
I have a CollectionOrderedFactory which makes a CollectionOrdered object. I would have thought that the return type for the makeCollection method in the factory would be CollectionOrdered<PayloadType>, as I have written below.
BUT
Phpstan comes back with "makeCollection() should return CollectionOrdered<PayloadType> but instead returns CollectionOrdered<HasPayloadInterface>". I just don't understand where the problem lies..
Here's the code:
/**
* Class HasPayloadInterface
* @template PayloadType
*/
interface HasPayloadInterface
{
}
/**
* Class CollectionOrdered
* @template PayloadType of HasPayloadInterface
* @implements HasPayloadInterface<PayloadType>
*/
class CollectionOrdered implements HasPayloadInterface
{
}
/**
* Class CollectionOrderedFactory
* @template PayloadType of HasPayloadInterface
*/
class CollectionOrderedFactory
{
/**
* makeCollection
* @return CollectionOrdered<PayloadType>
*/
public function makeCollection(): CollectionOrdered
{
return new CollectionOrdered();
}
}
Thanks in advance for some guidance.
I can see two issues in your code:
PayloadTyperefers to the generic interfaceHasPayloadInterface, but its type is not specified:If we substitute
PayloadTypefor its value, we'll obtain:@implements HasPayloadInterface<PayloadType of HasPayloadInterface>. In this expression it is apparent that the type parameter for the second reference toHasPayloadInterfaceis missing. If we add the missing type, we'll get something like this:But
PayloadTypeis ofHasPayloadInterface,so we end up with a cyclic reference.I guess there might be a typo in your code. I would instead expect to see a separate type for the payload, e.g.:
PayloadTypeto anything other thanHasPayloadInterfacein the following code:That is because there is no way for the user to specify the
PayloadType(not even implicitly).The error goes away when you allow the user to set the
PayloadTypein one way or another. For instance, in the following code, classes accept type information via constructor arguments:I admit that the code above is relatively useless, and you'll probably need another way of passing the type information into the classes, but it fixes the issue:
Here is how one could create a
CollectionOrdered<SimplePayload>: