使用 psalm 扩展接口的泛型

Extend a generic of an interface using psalm

我正在习惯使用 psalm,但我遇到了一个问题。我已经在 C# 中有了这个结构,它对我很有效。我真的不知道如何使用 psalm 解决这个问题。

我有一个 ContextInterface 和另一个实现它。

interface ContextInterface { public function getProductId(): int; }
interface SingleContextInterface extends ContextInterface { public function getWidth(): int; }

此外,我还为他们提供了策略界面。

/**
 * @template-covariant T as ContextInterface
 * @psalm-immutable
 */
interface CalculatorInterface
{
    /**
     * @psalm-param T $context
     */
    public function getPrice(ContextInterface $context): int;
}

/**
 * @template T as SingleContextInterface
 * @template-extends CalculatorInterface<T>
 * @psalm-immutable
 */
interface SingleDimensionalPriceCalculator extends CalculatorInterface { }

还有一个 class 实现接口:

/**
 * @template T as SingleContextInterface
 * @template-implements SingleDimensionalPriceCalculator<T>
 * @psalm-immutable
 */
class SingleDimensionCalculator implements SingleDimensionalPriceCalculator
{
    /**
     * @psalm-param SingleContextInterface $context
     */ 
    public function getPrice(ContextInterface $context): int
    {
        $context->getWidth();
        return 1;
    }
    
}

对于 getWidth() 方法调用,我收到以下错误:

ERROR: ImpureMethodCall - 37:19 - Cannot call an possibly-mutating method SingleContextInterface::getWidth from a mutation-free context

psalm.dev

上的例子

当然实际案例更复杂,包含的接口也更多

我想,问题是我将 CalculatorInterface 上的模板标记为协变。我可以在没有协变的情况下扩展它。

示例 psalm.dev