Intersection types

An annotation of the form Type1&Type2&Type3 is an Intersection Type. Any value must satisfy Type1, Type2 and Type3 simultaneously. Type1, Type2 and Type3 are all atomic types.

For example, after this statement in a PHPUnit test:

<?php

$hare = $this->createMock(Hare::class);

$hare will be an instance of a class that extends Hare, and implements \PHPUnit\Framework\MockObject\MockObject. So $hare is typed as Hare&\PHPUnit\Framework\MockObject\MockObject. You can use this syntax whenever a value is required to implement multiple interfaces.

Another use case is being able to merge object-like arrays:

/**
 * @psalm-type A=array{a: int}
 * @psalm-type B=array{b: int}
 *
 * @param A $a
 * @param B $b
 *
 * @return A&B
 */
function foo($a, $b) {
    return $a + $b;
}

The returned type will contain the properties of both A and B. In other words, it will be {a: int, b: int}.

Intersections are only valid for lists of only object types and lists of only object-like arrays.