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

DNF Types (PHP 8.2)

PHP PHP 8.2+ Advanced
debt(d1/e1/b1/t3)
d1 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'caught instantly (compiler/syntax error)' (d1). The most common mistake — forgetting parentheses around intersection in union — produces an immediate syntax/parse error in PHP. phpstan and psalm (listed tools) would also catch type logic issues, but the primary detection mechanism is the PHP parser itself before any tooling runs.

e1 Effort Remediation debt — work required to fix once spotted

Closest to 'one-line patch or single-call swap' (e1). The quick_fix is explicit: add parentheses around intersections and use (A&B)|null. This is a localised, single-declaration fix requiring no refactor.

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

Closest to 'minimal commitment' (b1). DNF types are a per-function/per-property type annotation. Misuse is localised to a single signature. There is no architectural gravity; the rest of the codebase is unaffected by a wrong DNF type on one method.

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

Closest to 'minor surprise (one edge case)' (t3). The misconception field states developers may read (A&B)|C as 'A and B or C' in the natural-language sense rather than the strict set-theory sense '(A&&B)||C'. This is a minor logical confusion but the correct reading is fairly intuitive once you see the parentheses, and the syntax enforces the grouping explicitly. It does not contradict other language constructs broadly.

About DEBT scoring →

TL;DR

PHP 8.2 DNF (Disjunctive Normal Form) types allow unions of intersections — (Countable&Iterator)|null — combining PHP 8.1 intersection types with union types.

Explanation

DNF type: (A&B)|C where intersections appear in parentheses within a union. PHP 8.1 added intersection types (A&B — object must implement both). PHP 8.2 adds DNF — combining intersections with unions: (Countable&Traversable)|null means either null OR an object implementing both Countable and Traversable. Rules: intersections must be in parentheses within unions. Cannot have redundant types. Cannot duplicate types within a union. Use cases: nullable intersection types (the most common: (A&B)|null), optional complex type parameters, return types that are either an intersection or a primitive.

Common Misconception

(A&B)|C means A and B or C — it means (A&&B)||C. An object satisfying both A and B, OR the value C.

Why It Matters

DNF types complete PHP's type system by allowing nullable intersection types — the most common real-world case (an object implementing multiple interfaces, or null).

Common Mistakes

  • Forgetting parentheses around intersection in union — syntax error.
  • Redundant types in union — (A&A)|B is invalid.
  • Using DNF where simple union suffices — only needed for intersections in unions.

Code Examples

✗ Vulnerable
// PHP 8.1 — no way to express nullable intersection:
function process(Countable&Iterator $items): void {} // Non-nullable only
✓ Fixed
// PHP 8.2 DNF — nullable intersection:
function process((Countable&Iterator)|null $items): void {
    if ($items === null) return;
    // $items is guaranteed to be both Countable AND Iterator
}

// Other uses:
function transform((Stringable&JsonSerializable)|array $data): string {}

Added 23 Mar 2026
Views 41
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 2 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 1 ping T 0 pings W 2 pings T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Perplexity 7 Amazonbot 6 Scrapy 5 Unknown AI 3 Ahrefs 3 SEMrush 3 Google 2 Meta AI 2 ChatGPT 1 Claude 1 Bing 1 Majestic 1 PetalBot 1
crawler 33 crawler_json 2 pre-tracking 1
DEV INTEL Tools & Severity
🔵 Info ⚙ Fix effort: Low
⚡ Quick Fix
Use (A&B)|null for nullable intersection types. Always put intersections in parentheses within unions. Only supported from PHP 8.2+.
📦 Applies To
PHP 8.2+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
[A-Z][a-z]+&[A-Z].*\|
Auto-detectable: ✓ Yes phpstan psalm
🤖 AI Agent
Confidence: Low False Positives: Medium ✗ Manual fix Fix: Low Context: Function


✓ schema.org compliant