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

Union Types (PHP 8.0)

PHP PHP 8.0+ Intermediate
debt(d5/e1/b3/t3)
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. The common mistake of using mixed instead of a precise union type, or relying on docblocks only, is caught by these tools rather than by compiler or default linter. No default linter catches this automatically.

e1 Effort Remediation debt — work required to fix once spotted

Closest to 'one-line patch or single-call swap' (e1). The quick_fix explicitly states: use int|string instead of mixed — a single-declaration change at the function signature level. Swapping mixed or a docblock annotation for a native union type is a one-line replacement per site.

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

Closest to 'localised tax' (b3). Union types apply across web, cli, and queue-worker contexts but the choice is localised to individual function/method signatures. Misuse (e.g. using mixed instead of a union) imposes a tax only on the components where those signatures live; the rest of the codebase is largely unaffected. Not a cross-cutting architectural burden.

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

Closest to 'minor surprise (one edge case)' (t3). The misconception field identifies one notable edge case: developers assume ?string and union types are equivalent, not realising ?string is strictly shorthand for string|null only and union types are a strict superset. Also, int|null vs ?int is a style confusion. These are minor surprises rather than catastrophic misunderstandings — a competent developer learns them quickly.

About DEBT scoring →

Also Known As

PHP union types PHP 8 union types int|string type

TL;DR

Allow a parameter, return value, or property to accept multiple specified types, declared as TypeA|TypeB.

Explanation

Union types (PHP 8.0) enable expressing that a value can be one of several types without resorting to mixed. For example, function getUser(int|string $id) accepts either an integer or string ID. The special null type can be included (int|null or the shorthand ?int for single types). PHP 8.0 also introduced the mixed pseudo-type as an explicit any. Union types interact with strict_types and are checked at runtime, throwing TypeError on mismatch.

Common Misconception

Union types are equivalent to nullable types with ?. ?string is shorthand for string|null only. Union types support arbitrary combinations like int|string|array and can include more than two types — they are a strict superset of nullable type syntax.

Why It Matters

PHP 8.0 union types (int|string) express that a parameter or return value can be one of several types — making previously implicit mixed usage explicit and type-checker verifiable.

Common Mistakes

  • Using mixed when a specific union like int|string|null is known — mixed disables type checking entirely.
  • Not handling all cases in the receiving code — a union type without exhaustive handling defeats the purpose.
  • Using union types instead of a proper abstraction — if a function accepts User|Admin, consider a common interface.
  • Forgetting that int|null is equivalent to ?int — both are valid but ?Type is more concise for nullable.

Avoid When

  • Do not use union types as a workaround for poor design — a parameter that accepts 5 different types usually needs refactoring.
  • Avoid mixed as a union type shortcut — it opts out of type checking entirely.

When To Use

  • Use union types to accurately express a parameter or return that can legitimately be one of several types.
  • Use int|string for IDs that may come from URLs (string) or database rows (int).

Code Examples

✗ Vulnerable
// mixed type — no type checking:
function process(mixed $input): mixed { /* anything goes */ }

// Union type — explicit and checkable:
function process(int|string $id): User|null {
    if (is_int($id)) return User::findById($id);
    return User::findBySlug($id);
}
✓ Fixed
// PHP 8.0 union types — accept multiple types
function formatId(int|string $id): string {
    return (string) $id;
}

// With null shorthand (PHP 7.1+)
function find(int $id): ?User { return null; } // = User|null

// PHP 8.0 — null in union
function process(int|null $value): void {}

// PHP 8.1 intersection types — value must satisfy ALL types
function handle(Countable&Iterator $collection): void {}

// PHP 8.2 DNF types — combination of union and intersection
function accept((Countable&Iterator)|array $items): void {}

Added 15 Mar 2026
Edited 31 Mar 2026
Views 133
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 1 ping T 1 ping F 0 pings S 0 pings S 2 pings M 1 ping T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 1 ping M 1 ping T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T
No pings yet today
No pings yesterday
Amazonbot 13 Scrapy 12 Perplexity 10 PetalBot 10 Ahrefs 8 Google 6 Bing 6 SEMrush 6 ChatGPT 3 Unknown AI 3 Twitter/X 2 Applebot 2 Meta AI 1
crawler 79 crawler_json 3
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
PHP php A server-side scripting language that generates web pages and APIs — the code runs on the server, and only its output (usually HTML or JSON) reaches the browser.

PHP is often the first server-side language people meet, and understanding its execution model — script starts fresh on every request, no memory between requests — explains most of how the web backend works: sessions, databases, and caching all exist to bridge that per-request amnesia.

💡 Start with PHP 8.x, declare(strict_types=1), and PDO — skip any tutorial that mentions mysql_query().

Ask Codex about PHP →
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Low
⚡ Quick Fix
Use int|string instead of mixed when a parameter genuinely accepts two types — union types give PHPStan precise information and catch misuse that mixed would silently allow
📦 Applies To
PHP 8.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
mixed param type where union would be precise; function accepting string|int documented in docblock only without native union type; PHP 8.0+ not using union types
Auto-detectable: ✓ Yes phpstan psalm rector
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✓ Auto-fixable Fix: Low Context: Function


✓ schema.org compliant