0

I'm trying out phpstan and psalm for php and I would like to write a class that can take different type of objects and return the right one based on the factory to call.

What I'm trying to achieve is that if I pass an object of type A to the Transformer, the compiler knows that a SuperA will be returned.

While I can go without errors in psalm (though I still get SuperA|SuperB instead of the right object), I got an error on what I'm passing in phpstan.

https://phpstan.org/r/4fce6f46-7aea-4f73-8259-df895910f064

https://psalm.dev/r/352e64ea95

Is there a way to do it?

1 Answer 1

3

So you want to get SuperA based on A and SuperB based on B.

I'd connect A+SuperA and B+SuperB together like this: https://phpstan.org/r/28e4e6ec-887b-4735-9b34-c034b4fa04ec

/**
 * @template TSuper of Super
 */
interface Common
{
}

/**
 * @implements Common<SuperA>
 */ 
class A implements Common
{
}

/**
 * @implements Common<SuperB>
 */ 
class B implements Common
{
}

interface Super
{
}

class SuperA implements Super
{
    public function callA(): void{}
}

class SuperB implements Super
{
    public function callB(): void{}
}

The factory then needs to have this signature:

/**
 * @template T of Super
 * @param Common<T> $obj
 * @return T
 */
public function transform($obj)
Sign up to request clarification or add additional context in comments.

2 Comments

Wow, it seems very good! Do you think I could do it in another way? Too bad A and B in my project come from an external source, so I don't have power on them!
You do - the stub files feature is for overriding 3rd party PHPDocs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.