Intersection Types in PHP 8.1

Since PHP 8.0, we can use union types which allows to provide two or more types for parameters, return values, and properties. Given value should be one of the specified types.

Since PHP 8.1, intersection types can be used. It requires value to be all of the specified class and interface types. We can specify any number of types which are combined by ampersand (&) using the syntax:


Intersection types are allowed anywhere types are accepted: parameters, return values, and properties.



class Storage
    private ArrayAccess&Countable $container;

    public function getContainer(): Countable&ArrayAccess
        return $this->container;

    public function setContainer(Countable&ArrayAccess $container): void
        $this->container = $container;

For example, with intersection types now possible to check if class implements both ArrayAccess and Countable interfaces. Parameter $container should be an instance of the class that implements both specified interfaces (e.g. CountableArrayObject class). Passing any instance of the class that does not implement both interfaces gives a fatal error.



class CountableArrayObject implements ArrayAccess, Countable
    public function offsetExists(mixed $offset): bool { return false; }
    public function offsetGet(mixed $offset): mixed { return null; }
    public function offsetSet(mixed $offset, mixed $value): void {}
    public function offsetUnset(mixed $offset): void {}
    public function count(): int { return 0; }

Nullable types

PHP allows to use nullable types (e.g. ?string or string|null). We cannot to use intersection types with nullable type notation. For example, ?Countable&ArrayAccess or Countable&ArrayAccess&null are incorrect.

Combination with union types

Intersection types together with union types cannot be used. For example, ArrayAccess&Countable|Iterator is illegal and cannot be used to define type.

Class and interface types

Only classes and interfaces can be used as part of the intersection types. Scalar types (bool, int, float, string), compound types (array, object, callable, iterable), void, mixed, never, and other types are not allowed. For example, int&float is illegal.

Duplicate types

Class or inteface cannot be used more than one time as part of the intersection types. This means that we cannot define type declarations such as ArrayAccess&Countable&ArrayAccess. It will produce a fatal error.

Leave a Comment

Your email address will not be published. Required fields are marked *