---
title: Allowed Subtypes
---

PHP language doesn't have a concept of sealed classes - a way to restrict class hierarchies and provide more control over inheritance. So any interface or non-final class can have an infinite number of child classes. But PHPStan provides an extension type to tell the analyzer the complete list of allowed child classes.

The implementation is all about applying the [core concepts](/developing-extensions/core-concepts) like [reflection](/developing-extensions/reflection) so check out that guide first and then continue here.

This is [the interface](https://apiref.phpstan.org/__BRANCH__/PHPStan.Reflection.AllowedSubTypesClassReflectionExtension.html) your extension needs to implement:

```php
namespace PHPStan\Reflection;

use PHPStan\Type\Type;

interface AllowedSubTypesClassReflectionExtension
{

	public function supports(ClassReflection $classReflection): bool;

	/** @return array<Type> */
	public function getAllowedSubTypes(ClassReflection $classReflection): array;

}
```

The implementation needs to be registered in your [configuration file](/config-reference):

```yaml
services:
	-
		class: MyApp\PHPStan\MySubtypesExtension
		tags:
			- phpstan.broker.allowedSubTypesClassReflectionExtension
```

When you implement this extension, it has a couple of effects:

* Smarter type inference when subtracting types from each other
* Error reporting when a disallowed class implements the restricted interface/extends a restricted parent class

<div class="bg-blue-100 border-l-4 border-blue-500 text-blue-700 p-4 mb-4" role="alert">

Sealed classes can also be defined with the [`@phpstan-sealed` PHPDoc tag](/writing-php-code/phpdocs-basics#sealed-classes).

</div>

An example
----------------

Let's say you have a class `Foo` and you want only `Bar` and `Baz` to be its child classes:

```php
namespace MyApp\PHPStan;

use PHPStan\Reflection\AllowedSubTypesClassReflectionExtension;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Type\ObjectType;

class MySubtypesExtension implements AllowedSubTypesClassReflectionExtension
{
	public function supports(ClassReflection $classReflection): bool
	{
		return $classReflection->getName() === Foo::class;
	}

	public function getAllowedSubTypes(ClassReflection $classReflection): array
	{
		return [
			new ObjectType(Bar::class),
			new ObjectType(Baz::class),
		];
	}
}
```

With this extension in place, let's consider this code:

```php
function foo(Foo $foo): void
{
    if ($foo instanceof Bar) {
        return;
    }

    // without the extension, $foo could be "any Foo, but not Bar"
    // with the extension, the only remaining possible type is Baz
    \PHPStan\dumpType($foo); // Baz
}
```

And if you try to extend Foo by a disallowed class:

```php
// Error: 'Type Lorem is not allowed to be a subtype of Foo.'
class Lorem extends Foo
{

}
```

This extension type can be used simply to hardcode a set of classes. But it can also be used [to read custom PHPDocs](/developing-extensions/reflection#retrieving-custom-phpdocs) or class attributes.
