PHP 8.0 : Union Types
18, April 2021

PHP is improving it's type system in every release. Type safety is a great approach to increase data integrity and reduce bugs overall in software. A combination of declare(strict_types=1); and static analyzer like psalm can really help us to improve our code quality. On PHP 7.4, we got things like Property Types & Contra/Co variant type support that helped us to define a specific type to property/parameter.

PHP 8.0 now enables us to define multiple type to a single property/parameter/return, which is called "Union Type".


Union Types

Currently we declare type this way:

<?php

class Foo
{
   public string $bar;

   public function baz(int $user): string
   {
       // something
   }
}

Here, we can only define a single type to $bar or $user or return type.

Actually, we already have two special union types:

  • Nullable type: we can define any type with nullable operator to accept null too. So, ?string is same as string|null
  • Iterable type: this type is actually accepts both array & traversable type, so same as array|traversable

But, now we can declare multiple types more practically. Multiple types are divided by pipe ( | ) sign.

<?php

class Foo
{
   public string|User $bar;

   public function baz(int|User|Profile $user): string|bool
   {
       // something
   }
}

as we can see, $bar can now contain either string or instance of User object. baz() now accept int or User or Profile object as $user parameter. It can also return either string value or boolean.

All the type definition will be checked during runtime, so PHP will throw error if we try to pass/return a invalid type.

Note: false is a new specially defined psudo-type. As the the name suggests, it can only represent false value. Some of the PHP internal functions return false as negative value (eg. not found), that's why false has been enabled to add to union type. true however, is not a valid type. use bool instead.


A new class has been defined for reflection purpose. ReflectionUnionType is used to get type information of union types.


Restriction regarding union types

  • void type can never be part of union types.
  • nullable types are not allowed to be part of union types. use |null instead.
  • false can't be used if bool is used in same place.
  • If object type is used, class types can't be used in same place.
  • if iterable type is used, array & Traversable types can't be used in same place.
  • duplicate types in union type will throw error.

Inheritance related restrictions:

  • Property types are invariant. So type must be subtype and supertype.
  • Parameter types are contravariant. We can only add wider type as union type. So super type is allowed.
  • Return types are covariant. We can only narrow down union types by sub type during inheritance.


After using union types, I am now looking forward to intersection type and type alias feature in PHP. Let's keep our finger crossed and hope we'll get them in near future. Till then, keep your code type safe.