Аннотация Psalm для типа возвращаемого значения в месте вызова метода/функции
Для демонстрации проблемы есть такой упрощенный реальный код:
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 **/
, только мне этот вариант не нравится, так как выглядит не очень красиво.