Skip to content

PHP Tutorial Object-Oriented PHP

Type Declarations in Classes

Lesson 207 of 369 2 min read By Deepak Paswan Updated Oct 5, 2026

Types make classes safer. You have seen typed properties and typed parameters separately. Here they work together.

Typed properties and methods

index.php
PHP
<?php
declare(strict_types=1);

class Invoice
{
    public function __construct(
        private int $id,
        private float $amount,
        private ?string $note = null,
    ) {}

    public function summary(): string
    {
        return "Invoice #{$this->id}: " . number_format($this->amount, 2);
    }
}

echo (new Invoice(7, 1234.5))->summary();
Output
OUTPUT
Invoice #7: 1,234.50

A class as a type

A parameter can require an object of a certain class.

index.php
PHP
<?php
class Customer
{
    public function __construct(public string $name) {}
}

class Order
{
    public function __construct(private Customer $customer) {}

    public function describe(): string
    {
        return "Order for " . $this->customer->name;
    }
}

echo (new Order(new Customer("Ana")))->describe();
Output
OUTPUT
Order for Ana

If you pass anything that is not a Customer, PHP throws a TypeError.

index.php
PHP
<?php
class Customer {}

function show(Customer $c): string
{
    return "ok";
}

try {
    show("Ana");
} catch (TypeError $e) {
    echo substr($e->getMessage(), 0, 52);
}
Output
OUTPUT
show(): Argument #1 ($c) must be of type Customer, s

self and static as return types

self is the class itself. static is the class that was called (it works with inheritance).

index.php
PHP
<?php
class Money
{
    public function __construct(public readonly int $cents) {}

    public function plus(Money $other): self
    {
        return new self($this->cents + $other->cents);
    }
}

echo (new Money(150))->plus(new Money(250))->cents;
Output
OUTPUT
400

Interfaces as types

Typing against an interface means “anything that can do this”. The code works with any class that implements it. Interfaces are in Interfaces.

index.php
PHP
<?php
interface Shape
{
    public function area(): float;
}

class Square implements Shape
{
    public function __construct(private float $side) {}

    public function area(): float
    {
        return $this->side ** 2;
    }
}

function printArea(Shape $shape): void
{
    echo "Area: " . $shape->area();
}

printArea(new Square(3));
Output
OUTPUT
Area: 9

Nullable and union class types

index.php
PHP
<?php
class Logger {}

class Service
{
    public function __construct(private ?Logger $logger = null) {}

    public function hasLogger(): bool
    {
        return $this->logger !== null;
    }
}

var_dump((new Service())->hasLogger());
Output
OUTPUT
bool(false)

Typed properties and arrays

PHP cannot say “array of Product”. Use array and document the items.

index.php
PHP
<?php
class Cart
{
    /** @var Product[] */
    private array $items = [];
}

Why types help

  • Wrong values are rejected at the boundary, with a clear message.
  • Editors can complete names and warn about mistakes.
  • A class’s signature tells you how to use it, without reading its body.
lightbulb
Type the boundary
Put types on every public method’s parameters and return values. Inside a small private method, they are still a good habit.