Is it possible to type hint more than one type?

Chris picture Chris · Oct 16, 2017 · Viewed 23.6k times · Source

Can I allow two different types using type hinting?

E.g. parameter $requester could be either of User or File:

function log (User|File $requester) {

}

Answer

yivi picture yivi · Nov 12, 2019

As of PHP 8.0, this will be possible with the inclusion of Union Types.

The proposal has been voted 61 in favour to 5 against, and the implementation is ready to go.

There was a previous RFC proposing this, mentioned in another answer, but that one ended up being rejected.

It will work exactly as the example in your question:

class F
{
   public function foo (File|Resource $f) : int|float { /** implement this**// }
}

Which means that F::foo() expects either a File or a resource, and will return an int or a float.

A couple additional points:

Nullability

Additionally, you can declare an union with null. A|null is equivalent to ?A, but a more complex declaration as A|B|null is also possible.

"False" pseudo-type

It's also possible use the false type as part of a union-type declaration. E.g. int|false. This is included mostly because of historical reasons, since some internal functions return false on some types of error conditions. See strpos() as an example.

More modern functions should probably return null or throw an exception in these situations, but this alternative is included to account for legacy code.

Adding and removing part of a union type on inheritance

It is legal to add union types for parameter type hints (thus, making the function less restrictive), and to remove union types for return type hints (making the return type more specific).

Given the class F from above, this is legal:

class G extends F
{
    public function foo(File|Resource|string $f) : int { /** **/ }
}

But this is not:

class H extends F
{
    public function foo(File $f) : int|float|bool { /** **/ }
}