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

Type Widening & Covariance/Contravariance

php PHP 7.4+ Advanced
debt(d2/e3/b3/t7)
d2 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'caught instantly' (d1) but slightly worse (d2) — PHP itself throws a fatal error for most LSP violations (narrowed params, widened returns), and PHPStan/Psalm catch the subtler variance cases at level 5+.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3) — quick_fix says adjust the override to widen params or narrow returns; usually a localised signature change in the subclass, occasionally touching a couple of related classes.

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

Closest to 'localised tax' (b3) — variance decisions affect class hierarchies and interface contracts in one component; doesn't define system shape but does shape inheritance design.

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

Closest to 'serious trap' (t7) — misconception field states devs assume strict invariance, and common_mistakes confirms covariance/contravariance directions are routinely confused (return narrows, params widen), contradicting naive 'same type everywhere' intuition.

About DEBT scoring →

Also Known As

covariance contravariance Liskov substitution type variance

TL;DR

PHP's rules for overriding method types in subclasses — return types are covariant (can narrow), parameter types are contravariant (can widen), enforced since PHP 7.4.

Explanation

Covariance: subclass return types can be more specific (narrower) — if parent returns Animal, child can return Cat. Contravariance: subclass parameter types can be broader (wider) — if parent accepts Cat, child can accept Animal. PHP 7.4 enforces Liskov Substitution Principle for typed properties (invariant). PHP 8.0+ supports covariant return types. The never return type is the bottom type — covariant in any position. Union types in parameters can widen: parent accepts Cat, child accepts Cat|Dog. This prevents runtime type errors when a subclass is used in place of its parent.

Common Misconception

PHP enforces strict type invariance in subclasses — PHP 7.4+ supports covariant return types and contravariant parameter types, following the Liskov Substitution Principle.

Why It Matters

Understanding covariance explains why a repository returning a specific entity type can implement an interface returning a base type — without covariance, every subtype would need duplicate interfaces.

Common Mistakes

  • Narrowing parameter types in subclasses — child accepts Cat, parent accepts Animal — PHP error.
  • Widening return types in subclasses — child returns Animal, parent returns Cat — PHP error.
  • Invariant property types — cannot change a typed property's type in a subclass.
  • Confusing covariance and contravariance — return types narrow (covariant), parameters widen (contravariant).

Code Examples

✗ Vulnerable
// Contravariance violation — narrows parameter incorrectly:
class AnimalShelter {
    public function add(Animal $animal): void { }
}
class CatShelter extends AnimalShelter {
    public function add(Cat $animal): void { } // Error: cannot narrow parameter type
    // If caller passes a Dog expecting AnimalShelter interface, CatShelter breaks
}
✓ Fixed
// Covariant return types — narrowing is allowed:
interface AnimalRepository {
    public function find(int $id): Animal;
}
class CatRepository implements AnimalRepository {
    public function find(int $id): Cat { } // Covariant: Cat is more specific than Animal — OK
}

// Contravariant parameters — widening is allowed:
class AnimalShelter {
    public function add(Cat $animal): void { }
}
class AllAnimalShelter extends AnimalShelter {
    public function add(Animal $animal): void { } // Contravariant: wider — OK
}

Tags


Added 16 Mar 2026
Edited 22 Mar 2026
Views 22
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 2 pings T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 1 ping 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 0 pings T 0 pings F
No pings yet today
No pings yesterday
Amazonbot 10 Perplexity 3 Unknown AI 2 Google 2 ChatGPT 2 Ahrefs 1
crawler 18 crawler_json 2
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
When overriding a method, you may widen parameter types (contravariance) or narrow return types (covariance) — PHPStan will flag violations of the Liskov substitution principle
📦 Applies To
PHP 7.4+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Child class method with stricter parameter type than parent; violates LSP; PHPStan level 5+ reports variance issues
Auto-detectable: ✓ Yes phpstan psalm
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: Class Tests: Update

✓ schema.org compliant