我从我的库中获得了简化的代码示例,由于我不理解的原因,psalm输出了警告。
class Example {
public const C_1 = 'val1';
public const C_2 = 'val2';
public const C_3 = 'val3';
/**
* @param self::C_1 | self::C_2 $c
*/
public function __construct(string $c)
{
if (!in_array($c, [self::C_1, self::C_2], true)) {
throw new InvalidArgumentException('Unsupported value');
}
}
}
字符串
在if (!in_array($c, [self::C_1, self::C_2], true))
行上显示警告,类型为DocblockTypeContradiction
,消息为Docblock-defined type "val1" for $c is always string(val1)
。
据我所知,psalm需要删除检查if (!in_array($c, [self::C_1, self::C_2], true))
,因为psalm已经检查了常量。但是如果一个使用我的库的用户在他的项目中不使用psalm怎么办?如何检查传递给构造函数的参数的正确性?
很抱歉我的英语不好。我希望我能解释这个问题。
2条答案
按热度按时间anauzrmj1#
问题是
@param
中的类型声明与方法签名中的声明不同。检查
in_array
绝对是有意义的,因为正如你所说,不是每个人都将使用诗篇作为保证。一种方法是只更改
@param
注解,让它知道您正在传递一个字符串,其中psalm is okay with:字符串
但这是多余的,因为PHP已经确保我们在那里有一个字符串,所以只需删除doc块works just as well。
cwdobuhd2#
如果您希望Psalm帮助静态验证只有有效的参数被传入,但同时您仍然希望代码在用户没有使用Psalm进行预验证的情况下进行运行时验证,您最好的选择是保留所有内容,然后使用
/** @psalm-suppress DocblockTypeContradiction */
内联抑制问题。字符串
https://psalm.dev/r/2e8e443bbd
Psalm展示这个问题是有意义的,因为这是Psalm的重点,验证可以在静态分析时验证的东西,所以它们不必在运行时验证。但是你的用例也是有意义的,我认为抑制这个问题是最好的选择。
或者,你可以使用一个字符串支持的enum。如果你指定你的枚举作为构造函数参数的类型,你就不需要运行时验证或Psalm注解,因为php会在运行时为你验证它,实际的php类型提示将是足够的信息让Psalm去关闭。然后Psalm仍然可以静态地验证只有正确的类型被传递给任何想要使用Psalm的人。