Аннотация к псалму для разнотипного шаблона
Мне нужно создать черту (или класс, если на то пошло), на основе которого я могу шаблонировать несколько типов; Я пробовал что-то вроде следующего (также описывающее проблему; контекст автомобиля предназначен только для иллюстрации проблемы, я знаю, что автомобиль должен быть агрегирован, а не составлен, но это не проблема для обсуждения):
/**
* @template TyreType of Tyre
* @template EngineType of Engine
*/
trait Car {
/**
* @return TyreType
*/
public function getTyre(): Tyre {
}
/**
* @return EngineType
*/
public function getEngine(): Engine{
}
}
trait SomeCar {
/**
* @use Car<AirlessTyre><DieselEngine>
*/
use Car;
public function test() {
$this->getEngine()->dieselSpecificMethod();
}
}
class Engine{}
class Tyre{}
class DieselEngine extends Engine {
public function dieselSpecificMethod() {}
}
class AirlessTyre extends Tyre {}
Проблема в том, что в PhpStorm я получаю «Потенциально полиморфный вызов. Engine не имеет элементов в своей иерархии» на
dieselSpecificMethod()
.
Итак, мои вопросы:
- Поддерживает ли псалом несколько типов шаблонов, поскольку я пытаюсь достичь
- Не хватает ли мне правильной семантики в приведенном выше примере; как мне это аннотировать?
- Или это просто ограничение PhpStorm
1 ответ
Psalm поддерживает несколько параметров типа. Правильный синтаксис для их использования:
GenericType<TA, TB>
(
GenericType<TA><TB>
который вы использовали, не распознается). После исправления этой проблемы (и еще нескольких подавленных, чтобы избавиться от ненужного шума) это становится:
<?php
/**
* @template TyreType of Tyre
* @template EngineType of Engine
*/
trait Car {
/**
* @return TyreType
* @psalm-suppress InvalidReturnType
*/
public function getTyre(): Tyre {
}
/**
* @return EngineType
* @psalm-suppress InvalidReturnType
*/
public function getEngine(): Engine{
}
}
trait SomeCar {
/**
* @use Car<AirlessTyre,DieselEngine>
*/
use Car;
public function test():void {
$this->getEngine()->dieselSpecificMethod();
$this->getEngine()->warp(9);
}
}
class FordCar { use SomeCar; }
class Engine{}
class Tyre{}
class DieselEngine extends Engine {
public function dieselSpecificMethod():void {}
}
class WarpEngine extends Engine {
public function warp(int $speed): void {}
}
class AirlessTyre extends Tyre {}
Псалом может сказать вам, что у Ford определенно нет возможностей двигателя деформации: https://psalm.dev/r/31343aafc3 . Обратите внимание на правильный синтаксис для ссылки на общую черту в
@use
аннотация.