Assertion syntax
Psalm’s assertion annotation supports a number of different assertions.
Psalm assertions are of the form
@psalm-assert(-if-true|-if-false)? (Assertion) (Variable or Property)
Assertion here can have many forms:
Regular assertions
is_xxx assertions
Most is_xxx PHP functions have companion assertions e.g. int for is_int. Here's the full list:
intfloatstringboolscalarcallablecountablearrayiterablenumericresourceobjectnull
So a custom version is_int could be annotated in Psalm as
<?php
/** @psalm-assert-if-true int $x */
function custom_is_int($x) {
return is_int($x);
}
Object type assertions
Any class can be used as an assertion e.g.
@psalm-assert SomeObjectType $foo
Generic assertions
Generic type parameters can also now be asserted e.g.
@psalm-assert array<int, string> $foo
Negated assertions
Any assertion above can be negated:
This asserts that $foo is not an int:
<?php
/** @psalm-assert !int $foo */
This asserts that $bar is not an object of type SomeObjectType:
<?php
/** @psalm-assert !SomeObjectType $bar */
Bool assertions
This asserts that $bar is true:
<?php
/** @psalm-assert true $bar */
This asserts that $bar is not false:
<?php
/** @psalm-assert !false $bar */
Equality assertions
Psalm also supports the equivalent of assert($some_int === $other_int) in the form
<?php
/** @psalm-assert =int $some_int */
There are two differences between the above assertion and
<?php
/** @psalm-assert int $some_int */
Firstly, the negation of =int has no meaning:
<?php
/** @psalm-assert-if-true =int $x */
function equalsFive($x) {
return is_int($x) && $x === 5;
}
function foo($y) : void {
if (equalsFive($y)) {
// $y is definitely an int
} else {
// $y might be an int, but it might not
}
}
function bar($y) : void {
if (is_int($y)) {
// $y is definitely an int
} else {
// $y is definitely not an int
}
}
Secondly, calling equalsFive($some_int) is not a RedundantCondition in Psalm, whereas calling is_int($some_int) is.