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

Disjunctive Normal Form Types (PHP 8.2)

php PHP 8.2+ Advanced
debt(d3/e3/b3/t5)
d3 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'default linter catches the common case' (d3). PHPStan and Psalm (both listed in detection_hints.tools) will flag type mismatches when DNF types are used incorrectly. These are standard tools in modern PHP workflows and catch the common case of malformed type expressions at the static analysis phase.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix indicates this is about expressing complex types natively in PHP 8.2 rather than via docblocks. Fixing a misuse typically involves restructuring the type declaration with proper parentheses — a localized change within method signatures, but may touch multiple signatures across a file or component.

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

Closest to 'localised tax' (b3). DNF types are an advanced type-system feature that applies to specific scenarios where intersection-union combinations are needed. The applies_to shows it works across contexts (web/cli/queue), but the feature itself is opt-in for complex type scenarios. It doesn't impose a system-wide architectural commitment — it's a localized enhancement where the complexity exists.

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

Closest to 'notable trap' (t5). The misconception field explicitly states developers think DNF types are 'just a combination of union and intersection types' when actually they enforce a specific structure requiring parentheses. Common mistakes include mixing AND/OR without parentheses and relying on operator precedence — this is a documented gotcha that most developers eventually learn but initially guess wrong about.

About DEBT scoring →

Also Known As

DNF types PHP 8.2 DNF intersection union types

TL;DR

DNF types combine intersection and union types with parentheses — (Countable&Iterator)|null — filling gaps in PHP 8.0/8.1's type system.

Explanation

PHP 8.2 introduced Disjunctive Normal Form (DNF) types, allowing intersection types (A&B) to be combined with union types using parentheses: (Countable&Iterator)|null means 'either something that is both Countable and Iterator, or null'. Prior to 8.2, intersection types and union types could not appear in the same declaration. DNF resolves real-world type scenarios common in library code — for example a parameter accepting either a validated PSR-7 request or null: (ServerRequestInterface&ValidatedRequest)|null. The type must be in strict DNF form with no redundant terms.

Common Misconception

DNF types are just a combination of union and intersection types. DNF types enforce a specific structure — intersections must be wrapped in parentheses within unions: (A&B)|C. This prevents ambiguous type combinations that would be impossible to evaluate consistently.

Why It Matters

Writing boolean conditions in DNF (OR of ANDs) makes complex conditionals readable and testable — each AND clause is an independent case that can be reasoned about in isolation.

Common Mistakes

  • Mixing AND and OR without parentheses and relying on operator precedence — && binds tighter than || in PHP, confusing readers.
  • Not simplifying redundant clauses — ($a && $b) || ($a && $b && $c) can be simplified to ($a && $b).
  • Deeply nested conditions instead of flat DNF — three levels of nesting is harder to read than two OR'd AND clauses.
  • Not extracting named boolean variables for complex sub-expressions — $isEligible = $age >= 18 && $hasConsent reads better than the raw condition.

Code Examples

✗ Vulnerable
// Hard to read — precedence unclear without parens:
if ($a || $b && $c || $d && $e && $f) { // What does this actually mean?

// DNF — clear and testable:
if (($a) || ($b && $c) || ($d && $e && $f)) {
✓ Fixed
function process((Stringable&Countable)|null $value): void {}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 18
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 2 pings 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 8 Google 5 Perplexity 4 Majestic 1 Ahrefs 1
crawler 16 crawler_json 3
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Low
⚡ Quick Fix
PHP 8.2 DNF types allow (A&B)|null — use them when you need to express 'an object implementing two interfaces, or null' which was previously only expressible via docblock
📦 Applies To
PHP 8.2+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Complex type that PHP 8.1 union types cannot express; @param (Countable&Iterator)|null in docblock when PHP 8.2 DNF type would be native
Auto-detectable: ✓ Yes phpstan psalm rector
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: Function

✓ schema.org compliant