Аннотация Psalm для типа возвращаемого значения в месте вызова метода/функции

Рейтинг: 1Ответов: 0Опубликовано: 07.07.2023

Для демонстрации проблемы есть такой упрощенный реальный код:

abstract class A
{
    /**
     * @var array<string, mixed>
     */
    private array $params;

    public function __construct(array $params)
    {
        static::validateParams($params);
        $this->params = $params;
    }

    final protected function getParamByKey(string $key): mixed
    {
        return $this->params[$key];
    }

    /**
     * @throws \InvalidArgumentException
     */
    abstract protected static function validateParams(array $params): void;
}

final class B extends A
{
    protected static function validateParams(array $params): void
    {
        if (!is_string($params['X'])) {
            throw new \InvalidArgumentException('Param X must be string');
        }
        if (!is_int($params['Y'])) {
            throw new \InvalidArgumentException('Param Y must be int');
        }
    }

    public function getParamX(): string
    {
        return $this->getParamByKey('X');
    }

    public function getParamY(): int
    {
        return $this->getParamByKey('Y');
    }
}

Теперь к сути. При прогоне этого кода через psalm для методов B::getParamX и B::getParamY я получаю по два варнинга: MixedReturnStatement: Could not infer a return type и MixedInferredReturnType: Could not verify return type 'string' for. Понятно что причина в том, что в объявлении метода getParamByKey, mixed указан как тип возвращаемого значения, из-за чего psalm делает вывод, что в B::getParamX и B::getParamY могут прилететь данные любого типа. Только вот в действительности это не так, поскольку перед вызовами B::getParamX и B::getParamY вызывается метод A::validateParams, который гарантирует корректность типов для обоих методов.

Вопрос: какую аннотацию можно задать, чтобы заставить psalm корректно выводить типы с учетом вызова A::validateParams?
Если так сделать нельзя, то можно ли в месте вызова $this->getParamByKey указать возвращаемый тип из getParamByKey? Чтобы это выглядело как-то так:

public function getParamX(): string
{
    return $this->getParamByKey('X'); /** @psalm-return string */
}

public function getParamY(): int
{
    return $this->getParamByKey('Y'); /** @psalm-return int */
}

Тут конечно можно создать переменную, присвоить ей возвращаемое значение, а потом задать ей аннотацию /** @var string $tmp **/, только мне этот вариант не нравится, так как выглядит не очень красиво.

Ответы

Ответов пока нет.