2018-01-30 06:14:36 +01:00
# Supported docblock annotations
Psalm supports a wide range of docblock annotations.
## PHPDoc tags
Psalm uses the following PHPDoc tags to understand your code:
2020-02-23 06:41:19 +01:00
2020-11-29 03:03:09 +01:00
- [`@var` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/var.html )
2023-04-25 08:44:17 +02:00
Used for specifying the types of properties and variables
2020-11-29 03:03:09 +01:00
- [`@return` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/return.html )
2018-01-30 17:31:17 +01:00
Used for specifying the return types of functions, methods and closures
2020-11-29 03:03:09 +01:00
- [`@param` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/param.html )
2018-01-30 17:31:17 +01:00
Used for specifying types of parameters passed to functions, methods and closures
2020-11-29 03:03:09 +01:00
- [`@property` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/property.html )
2018-01-30 17:31:17 +01:00
Used to specify what properties can be accessed on an object that uses `__get` and `__set`
2023-04-25 08:44:17 +02:00
- [`@property-read` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/property.html )
2018-01-30 17:31:17 +01:00
Used to specify what properties can be read on object that uses `__get`
2023-04-25 08:44:17 +02:00
- [`@property-write` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/property.html )
2018-01-30 17:31:17 +01:00
Used to specify what properties can be written on object that uses `__set`
2020-11-29 03:03:09 +01:00
- [`@method` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/method.html )
2020-06-17 04:20:34 +02:00
Used to specify which magic methods are available on object that uses `__call` .
2020-11-29 03:03:09 +01:00
- [`@deprecated` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/deprecated.html )
2018-01-30 17:31:17 +01:00
Used to mark functions, methods, classes and interfaces as being deprecated
2020-11-29 03:03:09 +01:00
- [`@internal` ](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/internal.html )
2023-04-25 08:44:17 +02:00
Used to mark classes, functions and properties that are internal to an application or library.
2023-04-25 22:09:04 +02:00
- [`@mixin` ](#mixins )
2023-04-25 08:43:43 +02:00
Used to tell Psalm that the current class proxies the methods and properties of the referenced class.
2018-01-30 06:14:36 +01:00
### Off-label usage of the `@var` tag
The `@var` tag is supposed to only be used for properties. Psalm, taking a lead from PHPStorm and other static analysis tools, allows its use inline in the form `@var Type [VariableReference]` .
If `VariableReference` is provided, it should be of the form `$variable` or `$variable->property` . If used above an assignment, Psalm checks whether the `VariableReference` matches the variable being assigned. If they differ, Psalm will assign the `Type` to `VariableReference` and use it in the expression below.
2022-04-27 07:46:13 +02:00
If no `VariableReference` is given, the annotation tells Psalm that the right-hand side of the expression, whether an assignment or a return, is of type `Type` .
2018-01-30 06:14:36 +01:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2018-01-30 06:14:36 +01:00
/** @var string */
$a = $_GET['foo'];
/** @var string $b */
$b = $_GET['bar'];
function bat(): string {
/** @var string */
return $_GET['bat'];
}
```
2023-04-25 22:09:04 +02:00
### @mixins
Adding `@mixin` to a classes docblock tells Psalm that the class proxies will proxy the methods and properties of the referenced class.
```php
class A
{
public string $a = 'A';
public function doA(): void
{
}
}
/**
* @mixin A
*/
class B
{
public string $b = 'B';
public function doB(): void
{
}
public function __call($name, $arguments)
{
(new A())->$name(...$arguments);
}
public function __get($name)
{
(new A())->$name;
}
}
$b = new B();
$b->doB();
$b->doA(); // works
echo $b->b;
echo $b->a; // works
```
2018-01-30 06:14:36 +01:00
## Psalm-specific tags
There are a number of custom tags that determine how Psalm treats your code.
2021-04-10 19:16:14 +02:00
### `@psalm-consistent-constructor`
See [UnsafeInstantiation ](../running_psalm/issues/UnsafeInstantiation.md )
### `@psalm-consistent-templates`
See [UnsafeGenericInstantiation ](../running_psalm/issues/UnsafeGenericInstantiation.md )
2020-11-27 23:05:26 +01:00
### `@param-out`, `@psalm-param-out`
2019-01-20 18:50:47 +01:00
This is used to specify that a by-ref type is different from the one that entered. In the function below the first param can be null, but once the function has executed the by-ref value is not null.
```php
2020-03-21 14:24:41 +01:00
< ?php
2019-01-20 18:50:47 +01:00
/**
* @param -out string $s
*/
function addFoo(?string & $s) : void {
if ($s === null) {
$s = "hello";
}
$s .= "foo";
}
```
2020-11-28 03:48:16 +01:00
### `@psalm-var`, `@psalm-param`, `@psalm-return`, `@psalm-property`, `@psalm-property-read`, `@psalm-property-write`, `@psalm-method`
2018-01-30 06:14:36 +01:00
2019-02-12 23:27:31 +01:00
When specifying types in a format not supported by phpDocumentor ([but supported by Psalm](#type-syntax)) you may wish to prepend `@psalm-` to the PHPDoc tag, so as to avoid confusing your IDE. If a `@psalm` -prefixed tag is given, Psalm will use it in place of its non-prefixed counterpart.
2018-01-30 06:14:36 +01:00
2021-03-27 02:20:23 +01:00
### `@psalm-ignore-var`
This annotation is used to ignore the `@var` annotation written in the same docblock. Some IDEs don't fully understand complex types like generics. To take advantage of such IDE's auto-completion, you may sometimes want to use explicit `@var` annotations even when psalm can infer the type just fine. This weakens the effectiveness of type checking in many cases since the explicit `@var` annotation overrides the types inferred by psalm. As psalm ignores the `@var` annotation which is co-located with `@psalm-ignore-var` , IDEs can use the type specified by the `@var` for auto-completion, while psalm can still use its own inferred type for type checking.
```php
< ?php
/** @return iterable< array-key , \DateTime > $f */
function getTimes(int $n): iterable {
while ($n--) {
yield new \DateTime();
}
};
/**
* @var \Datetime[] $times
* @psalm -ignore-var
*/
$times = getTimes(3);
// this trace shows "iterable< array-key , DateTime > " instead of "array< array-key , Datetime > "
/** @psalm -trace $times */
foreach ($times as $time) {
echo $time->format('Y-m-d H:i:s.u') . PHP_EOL;
}
```
2018-01-30 06:14:36 +01:00
### `@psalm-suppress SomeIssueName`
This annotation is used to suppress issues. It can be used in function docblocks, class docblocks and also inline, applying to the following statement.
Function docblock example:
```php
2020-03-21 14:24:41 +01:00
< ?php
2018-01-30 06:14:36 +01:00
/**
* @psalm -suppress PossiblyNullOperand
*/
function addString(?string $s) {
echo "hello " . $s;
}
```
Inline example:
```php
2020-03-21 14:24:41 +01:00
< ?php
2018-01-30 06:14:36 +01:00
function addString(?string $s) {
/** @psalm -suppress PossiblyNullOperand */
echo "hello " . $s;
}
```
2020-01-12 16:38:32 +01:00
`@psalm-suppress all` can be used to suppress all issues instead of listing them individually.
2021-10-28 10:44:37 +02:00
### `@psalm-assert`, `@psalm-assert-if-true`, `@psalm-assert-if-false`, `@psalm-if-this-is` and `@psalm-this-out`
2018-06-04 05:38:06 +02:00
2019-06-19 20:19:40 +02:00
See [Adding assertions ](adding_assertions.md ).
2019-06-19 07:09:46 +02:00
2018-01-30 06:14:36 +01:00
### `@psalm-ignore-nullable-return`
This can be used to tell Psalm not to worry if a function/method returns null. It’ s a bit of a hack, but occasionally useful for scenarios where you either have a very high confidence of a non-null value, or some other function guarantees a non-null value for that particular code path.
```php
2020-03-21 14:24:41 +01:00
< ?php
2018-01-30 06:14:36 +01:00
class Foo {}
function takesFoo(Foo $f): void {}
/** @psalm -ignore-nullable-return */
function getFoo(): ?Foo {
return rand(0, 10000) > 1 ? new Foo() : null;
}
takesFoo(getFoo());
```
### `@psalm-ignore-falsable-return`
This provides the same, but for `false` . Psalm uses this internally for functions like `preg_replace` , which can return false if the given input has encoding errors, but where 99.9% of the time the function operates as expected.
2023-04-20 08:14:17 +02:00
### `@psalm-seal-properties`, `@psalm-no-seal-properties`
2018-01-30 06:14:36 +01:00
2019-01-30 05:26:37 +01:00
If you have a magic property getter/setter, you can use `@psalm-seal-properties` to instruct Psalm to disallow getting and setting any properties not contained in a list of `@property` (or `@property-read` /`@property-write`) annotations.
2023-04-20 08:14:17 +02:00
This is automatically enabled with the configuration option `sealAllProperties` and can be disabled for a class with `@psalm-no-seal-properties`
2018-01-30 06:14:36 +01:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2018-01-30 06:14:36 +01:00
/**
2019-01-30 05:26:37 +01:00
* @property string $foo
* @psalm -seal-properties
*/
class A {
public function __get(string $name): ?string {
if ($name === "foo") {
return "hello";
}
}
public function __set(string $name, $value): void {}
}
$a = new A();
$a->bar = 5; // this call fails
```
2023-04-20 08:14:17 +02:00
### `@psalm-seal-methods`, `@psalm-no-seal-methods`
If you have a magic method caller, you can use `@psalm-seal-methods` to instruct Psalm to disallow calling any methods not contained in a list of `@method` annotations.
This is automatically enabled with the configuration option `sealAllMethods` and can be disabled for a class with `@psalm-no-seal-methods`
```php
< ?php
/**
* @method foo(): string
* @psalm -seal-methods
*/
class A {
public function __call(string $name, array $args) {
if ($name === "foo") {
return "hello";
}
}
}
$a = new A();
$b = $a->bar(); // this call fails
```
2019-05-11 18:15:45 +02:00
### `@psalm-internal`
Used to mark a class, property or function as internal to a given namespace. Psalm treats this slightly differently to
2019-06-28 19:59:09 +02:00
the PHPDoc `@internal` tag. For `@internal` , an issue is raised if the calling code is in a namespace completely
2019-05-11 18:15:45 +02:00
unrelated to the namespace of the calling code, i.e. not sharing the first element of the namespace.
2022-04-27 07:46:13 +02:00
In contrast for `@psalm-internal` , the docblock line must specify a namespace. An issue is raised if the calling code
2019-05-11 18:15:45 +02:00
is not within the given namespace.
2019-09-08 21:21:30 +02:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2019-05-11 18:15:45 +02:00
namespace A\B {
/**
2019-05-15 00:27:27 +02:00
* @internal
2019-05-11 18:15:45 +02:00
* @psalm -internal A\B
*/
class Foo { }
}
namespace A\B\C {
class Bat {
public function batBat(): void {
$a = new \A\B\Foo(); // this is fine
}
}
}
namespace A\C {
class Bat {
public function batBat(): void {
$a = new \A\B\Foo(); // error
}
}
}
```
2019-09-08 21:21:30 +02:00
### `@psalm-readonly` and `@readonly`
Used to annotate a property that can only be written to in its defining class's constructor.
```php
< ?php
class B {
/** @readonly */
public string $s;
2019-09-09 16:38:55 +02:00
2019-09-08 21:21:30 +02:00
public function __construct(string $s) {
$this->s = $s;
}
}
$b = new B("hello");
echo $b->s;
$b->s = "boo"; // disallowed
```
### `@psalm-mutation-free`
Used to annotate a class method that does not mutate state, either internally or externally of the class's scope.
2021-12-30 23:23:59 +01:00
This requires that the return value depend only on the instance's properties. For example, `random_int` is considered
mutating here because it mutates the random number generator's internal state.
2019-09-08 21:21:30 +02:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2019-09-08 21:21:30 +02:00
class D {
private string $s;
2019-09-09 16:38:55 +02:00
2019-09-08 21:21:30 +02:00
public function __construct(string $s) {
$this->s = $s;
}
2019-09-09 16:38:55 +02:00
2019-09-08 21:21:30 +02:00
/**
* @psalm -mutation-free
*/
public function getShort() : string {
return substr($this->s, 0, 5);
}
2019-09-09 16:38:55 +02:00
2019-09-08 21:21:30 +02:00
/**
* @psalm -mutation-free
*/
public function getShortMutating() : string {
$this->s .= "hello"; // this is a bug
return substr($this->s, 0, 5);
}
}
```
### `@psalm-external-mutation-free`
2019-09-09 20:52:30 +02:00
Used to annotate a class method that does not mutate state externally of the class's scope.
2019-09-08 21:21:30 +02:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2019-09-08 21:21:30 +02:00
class E {
private string $s;
2019-09-09 16:38:55 +02:00
2019-09-08 21:21:30 +02:00
public function __construct(string $s) {
$this->s = $s;
}
2019-09-09 16:38:55 +02:00
2019-09-08 21:21:30 +02:00
/**
* @psalm -external-mutation-free
*/
public function getShortMutating() : string {
$this->s .= "hello"; // this is fine
return substr($this->s, 0, 5);
}
/**
* @psalm -external-mutation-free
*/
public function save() : void {
file_put_contents("foo.txt", $this->s); // this is a bug
}
}
```
### `@psalm-immutable`
2019-09-09 16:38:55 +02:00
Used to annotate a class where every property is treated by consumers as `@psalm-readonly` and every instance method is treated as `@psalm-mutation-free` .
2019-09-08 21:21:30 +02:00
2020-01-02 20:09:11 +01:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2020-01-02 20:09:11 +01:00
/**
* @psalm -immutable
*/
abstract class Foo
{
public string $baz;
2021-12-30 23:23:59 +01:00
2020-01-02 20:09:11 +01:00
abstract public function bar(): int;
}
/**
* @psalm -immutable
*/
final class ChildClass extends Foo
{
public function __construct(string $baz)
{
$this->baz = $baz;
}
2021-12-30 23:23:59 +01:00
2020-01-02 20:09:11 +01:00
public function bar(): int
{
return 0;
}
}
$anonymous = new /** @psalm -immutable */ class extends Foo
{
public string $baz = "B";
2021-12-30 23:23:59 +01:00
2020-01-02 20:09:11 +01:00
public function bar(): int
{
return 1;
}
};
```
2019-09-08 21:25:12 +02:00
### `@psalm-pure`
Used to annotate a [pure function ](https://en.wikipedia.org/wiki/Pure_function ) - one whose output is just a function of its input.
```php
2020-03-21 14:24:41 +01:00
< ?php
2019-09-08 21:25:12 +02:00
class Arithmetic {
/** @psalm -pure */
public static function add(int $left, int $right) : int {
return $left + $right;
}
/** @psalm -pure - this is wrong */
public static function addCumulative(int $left) : int {
/** @var int */
static $i = 0; // this is a side effect, and thus a bug
$i += $left;
return $i;
}
}
echo Arithmetic::add(40, 2);
echo Arithmetic::add(40, 2); // same value is emitted
echo Arithmetic::addCumulative(3); // outputs 3
echo Arithmetic::addCumulative(3); // outputs 6
```
2020-10-15 01:59:44 +02:00
On the other hand, `pure-callable` can be used to denote a callable which needs to be pure.
```php
/**
* @param pure-callable(mixed): int $callback
*/
function foo(callable $callback) {...}
// this fails since random_int is not pure
foo(
/** @param mixed $p */
fn($p) => random_int(1, 2)
);
```
2020-02-02 21:38:41 +01:00
### `@psalm-allow-private-mutation`
2020-02-02 13:46:39 +01:00
2020-02-02 21:38:41 +01:00
Used to annotate readonly properties that can be mutated in a private context. With this, public properties can be read from another class but only be mutated within a method of its own class.
2020-02-02 13:46:39 +01:00
```php
2020-03-21 14:24:41 +01:00
< ?php
2020-02-02 13:46:39 +01:00
class Counter {
2020-02-02 21:38:41 +01:00
/**
* @readonly
* @psalm -allow-private-mutation
2021-12-30 23:23:59 +01:00
*/
2020-02-02 13:46:39 +01:00
public int $count = 0;
2021-12-30 23:23:59 +01:00
2020-02-02 13:46:39 +01:00
public function increment() : void {
$this->count++;
}
}
$counter = new Counter();
echo $counter->count; // outputs 0
2020-02-02 21:03:17 +01:00
$counter->increment(); // Method can mutate property
2020-02-02 13:46:39 +01:00
echo $counter->count; // outputs 1
2020-02-02 21:38:41 +01:00
$counter->count = 5; // This will fail, as it's mutating a property directly
2020-02-02 13:46:39 +01:00
```
2020-02-02 21:56:08 +01:00
### `@psalm-readonly-allow-private-mutation`
This is a shorthand for the property annotations `@readonly` and `@psalm-allow-private-mutation` .
```php
2020-03-21 14:24:41 +01:00
< ?php
2020-02-02 21:56:08 +01:00
class Counter {
/**
* @psalm -readonly-allow-private-mutation
2021-12-30 23:23:59 +01:00
*/
2020-02-02 21:56:08 +01:00
public int $count = 0;
2021-12-30 23:23:59 +01:00
2020-02-02 21:56:08 +01:00
public function increment() : void {
$this->count++;
}
}
$counter = new Counter();
echo $counter->count; // outputs 0
$counter->increment(); // Method can mutate property
echo $counter->count; // outputs 1
$counter->count = 5; // This will fail, as it's mutating a property directly
```
2020-04-06 18:42:22 +02:00
### `@psalm-trace`
You can use this annotation to trace inferred type (applied to the *next* statement).
```php
< ?php
2021-12-30 23:23:59 +01:00
/** @psalm -trace $username */
2020-04-06 18:42:22 +02:00
$username = $_GET['username']; // prints something like "test.php:4 $username: mixed"
```
2023-04-26 21:38:44 +02:00
*Note*: it throws [special low-level issue ](../running_psalm/issues/Trace.md ).
To see it, you can set the global `errorLevel` to 1, or invoke Psalm with
`--show-info=true` , but both these solutions will probably result in a lot of
output. Another solution is to selectively bump the error level of the issue,
so that you only get one more error:
```xml
<!-- psalm.xml -->
< issueHandlers >
< Trace errorLevel = "error" / >
< / issueHandlers >
```
2020-04-09 03:03:05 +02:00
2022-02-17 17:26:28 +01:00
### `@psalm-check-type`
You can use this annotation to ensure the inferred type matches what you expect.
```php
< ?php
/** @psalm -check-type $foo = int */
$foo = 1; // No issue
/** @psalm -check-type $bar = int */
$bar = "not-an-int"; // Checked variable $bar = int does not match $bar = 'not-an-int'
```
### `@psalm-check-type-exact`
Like `@psalm-check-type` , but checks the exact type of the variable without allowing subtypes.
```php
< ?php
/** @psalm -check-type-exact $foo = int */
$foo = 1; // Checked variable $foo = int does not match $foo = 1
```
2020-06-17 02:55:39 +02:00
### `@psalm-taint-*`
See [Security Analysis annotations ](../security_analysis/annotations.md ).
2020-10-07 00:58:25 +02:00
### `@psalm-type`
This allows you to define an alias for another type.
```php
< ?php
/**
2022-11-12 02:43:19 +01:00
* @psalm -type PhoneType = array{phone: string}
2020-10-07 00:58:25 +02:00
*/
class Phone {
/**
* @psalm -return PhoneType
*/
public function toArray(): array {
return ["phone" => "Nokia"];
}
}
```
### `@psalm-import-type`
You can use this annotation to import a type defined with [`@psalm-type` ](#psalm-type ) if it was defined somewhere else.
```php
< ?php
/**
* @psalm -import-type PhoneType from Phone
*/
class User {
/**
* @psalm -return PhoneType
*/
public function toArray(): array {
return array_merge([], (new Phone())->toArray());
}
}
```
You can also alias a type when you import it:
```php
< ?php
/**
* @psalm -import-type PhoneType from Phone as MyPhoneTypeAlias
*/
class User {
/**
* @psalm -return MyPhoneTypeAlias
*/
public function toArray(): array {
return array_merge([], (new Phone())->toArray());
}
}
```
2020-11-28 03:48:16 +01:00
### `@psalm-require-extends`
2022-08-20 23:29:03 +02:00
The `@psalm-require-extends` annotation allows you to define the requirements that a trait imposes on the using class.
2020-11-28 03:48:16 +01:00
```php
2021-04-13 05:50:52 +02:00
< ?php
2020-11-28 03:48:16 +01:00
abstract class DatabaseModel {
// methods, properties, etc.
}
/**
* @psalm -require-extends DatabaseModel
*/
trait SoftDeletingTrait {
// useful but scoped functionality, that depends on methods/properties from DatabaseModel
}
class MyModel extends DatabaseModel {
// valid
use SoftDeletingTrait;
}
class NormalClass {
// triggers an error
use SoftDeletingTrait;
}
```
### `@psalm-require-implements`
Behaves the same way as `@psalm-require-extends` , but for interfaces.
2021-04-21 07:02:25 +02:00
### `@no-named-arguments`
This will prevent access to the function or method tagged with named parameters (by emitting a `NamedArgumentNotAllowed` issue).
Incidentally, it will change the inferred type for the following code:
```php
< ?php
function a(int ...$a){
var_dump($a);
}
```
2022-04-27 07:46:13 +02:00
The type of `$a` is `array<array-key, int>` without `@no-named-arguments` but becomes `list<int>` with it, because it excludes the case where the offset would be a string with the name of the parameter
### `@psalm-ignore-variable-property` and `@psalm-ignore-variable-method`
Instructs Psalm to ignore variable property fetch / variable method call when looking for dead code.
```php
class Foo
{
// this property can be deleted by Psalter,
// as potential reference in get() is ignored
public string $bar = 'bar';
public function get(string $name): mixed
{
/** @psalm -ignore-variable-property */
return $this->{$name};
}
}
```
When Psalm encounters variable property, it treats all properties in given class as potentially referenced.
2023-04-26 21:38:44 +02:00
With `@psalm-ignore-variable-property` annotation, this reference is ignored.
2022-04-27 07:46:13 +02:00
While `PossiblyUnusedProperty` would be emitted in both cases, using `@psalm-ignore-variable-property`
would allow [Psalter ](../manipulating_code/fixing.md ) to delete `Foo::$bar` .
`@psalm-ignore-variable-method` behaves the same way, but for variable method calls.
### `@psalm-yield`
Used to specify the type of value which will be sent back to a generator when an annotated object instance is yielded.
```php
< ?php
/**
* @template -covariant TValue
* @psalm -yield TValue
*/
interface Promise {}
/**
* @template -covariant TValue
* @template -implements Promise< TValue >
*/
class Success implements Promise {
/**
* @psalm -param TValue $value
*/
public function __construct($value) {}
}
/**
* @return Promise< string >
*/
function fetch(): Promise {
2022-12-22 15:43:55 +01:00
return new Success('{"data":[]}');
2022-04-27 07:46:13 +02:00
}
function (): Generator {
$data = yield fetch();
// this is fine, Psalm knows that $data is a string
return json_decode($data);
};
```
This annotation supports only generic types, meaning that e.g. `@psalm-yield string` would be ignored.
2021-04-21 07:02:25 +02:00
2023-03-20 12:25:06 +01:00
### `@api`, `@psalm-api`
2022-12-22 15:43:55 +01:00
2023-03-20 12:17:17 +01:00
Used to tell Psalm that a class or method is used, even if no references to it can be
2022-12-22 15:43:55 +01:00
found. Unused issues will be suppressed.
For example, in frameworks, controllers are often invoked "magically" without
any explicit references to them in your code. You should mark these classes with
`@psalm-api` .
```php
/**
* @psalm -api
*/
class UnreferencedClass {}
```
2023-04-20 18:25:11 +02:00
### `@psalm-inheritors`
Used to tell Psalm that a class can only be extended by a certain subset of classes.
For example,
```php
2023-05-03 09:41:59 +02:00
< ?php
2023-04-20 18:25:11 +02:00
/**
* @psalm -inheritors FooClass|BarClass
*/
class BaseClass {}
2023-05-03 09:41:59 +02:00
class FooClass extends BaseClass {}
class BarClass extends BaseClass {}
2023-04-20 18:25:11 +02:00
class BazClass extends BaseClass {} // this is an error
```
2018-01-30 06:14:36 +01:00
## Type Syntax
2020-11-29 03:03:09 +01:00
Psalm supports PHPDoc’ s [type syntax ](https://docs.phpdoc.org/latest/guide/guides/types.html ), and also the [proposed PHPDoc PSR type syntax ](https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md#appendix-a-types ).
2018-01-30 06:14:36 +01:00
2019-01-02 19:56:43 +01:00
A detailed write-up is found in [Typing in Psalm ](typing_in_psalm.md )