← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Intersection Types (PHP 8.1)

php PHP 8.1+ Intermediate
debt(d5/e3/b3/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list phpstan, psalm, and rector — all specialist static analysis tools. Misuse (e.g. combining non-interface types, using intersection where a named interface would be cleaner, or trying to mix with union types before PHP 8.2 DNF) won't be caught by a default linter but will surface under these specialist tools.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix describes replacing a custom bridging interface or imprecise type hint with an intersection type (Countable&Iterator), or the reverse — extracting a named interface when overuse occurs. This is a targeted change within one component or signature, not a single-line swap but not a cross-cutting refactor either.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). Intersection types are scoped to individual function/method signatures. The applies_to scope is broad (web, cli, queue-worker) but the choice itself is localised — a type hint change in one signature doesn't propagate structural weight across the codebase unless the intersection pattern recurs widely, in which case a named interface would be extracted anyway.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap' (t5). The misconception field explicitly states developers confuse intersection types with union types — thinking they are two ways to express the same thing. Additionally, the common_mistakes list includes the non-obvious restriction that PHP 8.1 intersection types cannot be combined with union types in the same declaration (requiring PHP 8.2 DNF types), and the constraint that only interfaces/classes are allowed, not scalars. These are documented gotchas most devs learn the hard way.

About DEBT scoring →

Also Known As

PHP intersection types PHP 8.1 intersection combined interface types

TL;DR

Require a value to satisfy multiple type constraints simultaneously, declared as TypeA&TypeB — useful for combining interfaces.

Explanation

Intersection types (PHP 8.1) declare that a value must implement all of the listed types. For example, function process(Countable&Iterator $collection) requires the argument to implement both interfaces. This is especially useful in generic-style code that needs an object to fulfil multiple contracts without creating a new combined interface. Intersection types only work with class/interface types, not with scalar types, and cannot currently be combined with union types in the same declaration (PHP 8.1).

Common Misconception

Intersection types and union types are two ways to express the same thing. Union types mean "one of these types"; intersection types mean "all of these types simultaneously" — useful for requiring an argument to implement multiple interfaces at once.

Why It Matters

PHP 8.1 intersection types (A&B) require a value to satisfy multiple type constraints simultaneously — useful for parameters that must implement several interfaces at once.

Common Mistakes

  • Using intersection types where a single interface combining both contracts would be cleaner.
  • Combining non-interface types in an intersection — PHP only allows interfaces and classes, not scalar types.
  • Not realising intersection types cannot be used with union types in the same declaration in PHP 8.1 — use PHP 8.2 DNF types (A&B)|null for that.
  • Overusing intersection types making signatures hard to read — extract a named interface when the combination recurs.

Code Examples

✗ Vulnerable
// PHP 8.1 — cannot combine intersection and union:
function process(Countable&Iterator|null $input): void {} // Error in PHP 8.1

// PHP 8.2 DNF types solve this:
function process((Countable&Iterator)|null $input): void {} // Valid in PHP 8.2+
✓ Fixed
// PHP 8.1 — value must satisfy ALL listed types simultaneously
function process(Iterator&Countable \$collection): void {
    echo count(\$collection);      // Countable
    foreach (\$collection as \$item) { handle(\$item); } // Iterator
}

// PHP 8.2 DNF types — mix union + intersection:
function accept((Iterator&Countable)|array \$items): void {}

// Practical: enforce a collection interface
interface Collection extends Countable, Iterator {}

function paginate(Countable&Iterator \$items, int \$perPage = 20): array {
    return ['total' => count(\$items), 'items' => iterator_to_array(\$items)];
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 33
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 1 ping S 1 ping M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 5 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S
No pings yet today
No pings yesterday
Amazonbot 7 Perplexity 7 ChatGPT 3 Google 3 Ahrefs 2 Unknown AI 2 SEMrush 2 Majestic 1
crawler 24 crawler_json 3
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Low
⚡ Quick Fix
Use intersection types (Countable&Iterator) in PHP 8.1 to express that a parameter must implement multiple interfaces — previously required a custom interface extending both
📦 Applies To
PHP 8.1+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Custom interface extending two other interfaces just to use as type hint; accepting mixed or object when intersection type would be precise
Auto-detectable: ✓ Yes phpstan psalm rector
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: Medium ✗ Manual fix Fix: Low Context: Function

✓ schema.org compliant