Как написать дженерики для фабрик с помощью psalm и phpstan

Я пробую phpstan и psalm для php, и я хотел бы написать класс, который может принимать разные типы объектов и возвращать правильный на основе вызываемой фабрики.

Я пытаюсь добиться того, чтобы, если я передаю объект типа A в Transformer, компилятор знает, что будет возвращен SuperA.

Хотя я могу обойтись без ошибок в псалме (хотя я все еще получаю SuperA|SuperB вместо нужного объекта), у меня есть ошибка в том, что я передаю в phpstan.

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

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

Как это сделать?

1 ответ

Решение

Итак, вы хотите получить SuperA на основе A и SuperB на основе B.

Я бы соединил A+SuperA и B+SuperB вместе следующим образом: 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{}
}

Затем фабрика должна иметь эту подпись:

/**
 * @template T of Super
 * @param Common<T> $obj
 * @return T
 */
public function transform($obj)
Другие вопросы по тегам