Union-типы (PHP 8)

Тема дорожной карты · PHP Developer

Union-типы — фича PHP 8.0, позволяющая объявить параметр, возвращаемое значение или свойство класса как один из нескольких типов: int|string, Order|null, Collection|array. Раньше такие сигнатуры выражались только в PHPDoc-аннотациях и проверялись статически (phpstan/psalm), но не runtime. Теперь PHP проверяет union на месте: попытка передать bool, когда сигнатура говорит int|string, выбрасывает TypeError ещё на входе. Синтаксис: public function find(int|string $id): User|null — компактно, читабельно, без зависимости от внешнего тулинга.

Как это работает

Union — это операция "ИЛИ" над типами. PHP проверяет каждое значение по списку слева направо; первое совпадение принимается. null в union пишут явно (int|null или сокращённо ?int — формы эквивалентны). С Stringable и интерфейсами union ведёт себя обычно — value считается совместимым, если реализует один из перечисленных интерфейсов. Запрещены void|null и mixed|<что-то>mixed уже включает всё. Union можно сочетать с intersection (PHP 8.1): (Iterator&Countable)|Generator. Поведение в strict-mode (declare(strict_types=1)) ужесточает приведение — никакого автокаста между типами union.

Когда применять

Union полезны на тех границах кода, где API исторически принимал «одно из»: ID может быть числовым или slug-строкой, результат find()Entity|null. Не злоупотребляйте: широкий union (int|string|float|bool) — сигнал, что вы переусложнили API; декомпозируйте на отдельные методы. Для PHP 7.4 и старше используйте PHPDoc @param int|string $id и phpstan — на runtime проверки не будет, но статанализ выловит.

Типичные ошибки

Использование mixed через union вместо честной типизации (int|string|float|bool|array|object = mixed, лучше так и написать). Забывают null в union — параметр ?intint без значения по умолчанию. Перегружают union в публичном API и теряют возможность статанализа: вызывающим приходится if/else на каждый возможный тип. Ещё одна частая ловушка — попытка вернуть значение, формально подходящее под несколько ветвей union: PHP выбирает первую совместимую слева направо, и результат может стать неожиданным после рефакторинга порядка типов. Поэтому при ревью union-сигнатур всегда явно проверяйте конкретные типы через instanceof и is_* внутри функции, а не полагайтесь на интуицию.

Связанные понятия

Полезные ресурсы