Union Types in PHP 8.0

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 union types. A union type allows providing values of two or more types, instead of a 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 will be the same as ?type. For example, string|null is equivalent to ?string.

Since PHP 8.2, null type can be used as a standalone type. For example, function test(null $param): null is a valid function declaration.

Important note:

  • 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 an array or object that implements the 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 the 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 the 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 type.

UserRepository.php

<?php

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

Since PHP 8.2, false type can be used as a standalone type. For example, function test(false $param): false is a valid function declaration.

The true type

Since PHP 8.2, true can be used as a type. For example, function test(true $param): true is a valid function declaration. Also, true type can be used as part of the union type (e.g. true|int).

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 and true types cannot be used together with bool type. It means that bool|false and bool|true are not allowed.
  • The false and true types cannot be used together. The false|true is not allowed. The bool type should be used instead.
  • 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

Cancel reply

Your email address will not be published.