2

I have a problem with @return types. It seems that either it's a bug in PHPStan or I'm doing something wrong.

Error:

abstract class Aclass {}
final class Bclass extends Aclass {}
final class Cclass extends Aclass {}

final class Factory {
    /**
     * @template T of Aclass
     * @param class-string<T> $param
     * @return T
     */
    public function create($param) {
        // some kind of factory logic
        return new Bclass();
    }
}

No error:

abstract class Aclass {}
final class Bclass extends Aclass {}
final class Cclass extends Aclass {}

final class Factory {
    /**
     * @template T of Aclass
     * @param class-string<T> $param
     * @return Aclass
     */
    public function create($param) {
        // some kind of factory logic
        return new Bclass();
    }
}

Why does PHPStan give me an error? Isn't @template T of Aclass + @return T the same as @return Aclass?

I'm expecting no errors.

1 Answer 1

0

T of Aclass means that T is either Aclass or an inherited class.

So, in this case:

final class Factory {
    /**
     * @template T of Aclass
     * @param class-string<T> $param
     * @return T
     */
    public function create($param) {
        // some kind of factory logic
        return new Bclass();
    }
}

T may be Cclass. But the method returns an instance of Bclass, which does not extend Cclass, hence the error.

This code gives no error:

final class Factory {
    /**
     * @template T of Aclass
     * @param class-string<T> $param
     * @return T
     */
    public function create($param) {
        // some kind of factory logic
        return new $param();
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Unfortunately return new $param(); is not working for me because of different naming constructors. public function create($param) { // some kind of factory logic if ($condition1) { return Bclass::createOne(); } elseif ($condition2) { return Bclass::createTwo(); } elseif ($condition3) { return Cclass::createThree(); } // etc. throw new \InvalidArgumentException('Invalid class name'); }

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.