Union Types in PHP 8.0

In versions prior to PHP 8.0, we can specify a single type for parameters, return values, and properties.

Since PHP 8.0, we can use a union types. A union type allows to provide values of two or more types, instead of single one. We can specify any number of types which are joined by a vertical line (|) using the syntax:

type_1|type_2|...|type_n

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

Number.php

<?php

class Number
{
    private float|int $num;

    public function getNum(): float|int
    {
        return $this->num;
    }

    public function setNum(float|int $num): void
    {
        $this->num = $num;
    }
}

Nullable types

Since PHP 7.1, we can use nullable types. Type declarations can be declared as nullable by prefixing a question sign (?) to the type. For example, a string or null can be declared as ?string. Since PHP 8.0, we can declare nullable types as type|null. It it will be the same as ?type. For example, string|null is equivalent to ?string.

There are some important notes:

  • The null type only allowed as part of the union types and cannot be used as a standalone type.
  • Type declarations can have more than one type and null. For example, float|int|null. But it cannot be declared as ?float|int.

The iterable type

Since PHP 7.1, we can use iterable pseudo-type. It accepts array or object that implements Traversable interface. Since PHP 8.0, we can declare iterable pseudo-type as array|Traversable. Both of them are equivalent.

The void type

Since PHP 7.1, we can use void return type. It means that the function has no return value. The void type cannot be used as part of the union types. For example, string|void is illegal and cannot be used to define return type.

The false type

Most of time we use null as return value to indicate an error or the absence of a return value. For example, if we have a class method that finds the user by ID, it might return null to indicate that user was not found. However, many PHP core functions and legacy libraries use false as return value for this purpose. Since PHP 8.0, we can use the false pseudo-type.

UserRepository.php

<?php

class UserRepository
{
    public function find(int $id): User|false
    {
        // ...
    }
}

There are some important notes:

  • The false pseudo-type cannot be used as a standalone type and nullable standalone type. It means that false, false|null and ?false are not allowed.
  • The false pseudo-type can be used in all places where types are accepted: parameters, return values, and properties.
  • There is no true pseudo-type. We need to use bool type instead.

Duplicate types

Duplicate types are not allowed. It means that we cannot define type declarations such as int|int or int|INT. It will produce a fatal error.

Redundant types

Redundant types are not allowed. This includes:

  • The false pseudo-type cannot be used together with bool type. It means that bool|false is not allowed.
  • The iterable pseudo-type cannot be used together with array or Traversable. It means that array|iterable, Traversable|iterable or array|Traversable|iterable are not allowed.
  • The object type cannot be used together with a class types. It means that User|object is not allowed.

Note that we can use a parent class and a child class as part of the union types because the type declarations are checked only at compile-time. For example, if class Cat extends class Animal, then Animal|Cat is a legal union type, even though it could be reduced to just Animal. The following code is valid:

<?php

class Animal {}
class Cat extends Animal {}

function test(Animal|Cat $animal) {}

test(new Animal());
test(new Cat());

Leave a Comment

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