Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

Typed properties in PHP enforce specific data types on class properties at runtime. Introduced in PHP 7.4, they guarantee that a property will only ever hold a value of the declared type, throwing a TypeError upon the assignment of an incompatible type.

Syntax and Declarations

Type declarations are placed between the visibility modifier and the property name. PHP supports scalar types, compound types, object types, and modern type combinations (Union, Intersection, and Disjunctive Normal Form).
class TypeDemonstration {
    // Scalar types
    public int $integer;
    protected float $floatingPoint;
    private bool $boolean;
    public string $string;

    // Compound and Object types
    public array $array;
    public iterable $iterable;
    public object $object;
    public stdClass $classInstance;

    // Nullable types (prefixed with '?')
    public ?string $nullableString;

    // Default values (must match the declared type)
    public int $withDefault = 42;

    // Union types (PHP 8.0+)
    public int|float $number;

    // Intersection types (PHP 8.1+)
    public Iterator&Countable $traversableCollection;
}

The Uninitialized State and unset()

A critical mechanic of typed properties is the uninitialized state. Unlike untyped properties, which default to null, a typed property without an explicit default value remains uninitialized until assigned. Accessing an uninitialized typed property—even if the type is nullable—results in a fatal Error.
class Entity {
    public int $id;
    public ?string $name;
}

$entity = new Entity();

// Fatal error: Typed property Entity::$id must not be accessed before initialization
echo $entity->id; 
To safely check if a typed property has been initialized, use the isset() construct, which returns false for uninitialized properties without throwing an error. Additionally, using unset() on a typed property strips its value and returns it directly to the uninitialized state. This is a unique behavior compared to untyped properties, where unset() simply makes them undefined or null.
class Counter {
    public int $count = 10;
}

$counter = new Counter();
unset($counter->count);

// Fatal error: Typed property Counter::$count must not be accessed before initialization
echo $counter->count;

Type Coercion and Strict Typing

The behavior of typed property assignments depends on the strict_types directive.
  • Weak Typing (Default): PHP will attempt to coerce incompatible types into the declared type if a safe conversion exists (e.g., assigning the string "100" to an int property results in the integer 100).
  • Strict Typing (declare(strict_types=1);): PHP disables coercion. Assigning a value of the wrong type immediately throws a TypeError.
declare(strict_types=1);

class StrictExample {
    public int $count;
}

$obj = new StrictExample();
$obj->count = "10"; // TypeError: Cannot assign string to property StrictExample::$count of type int

Inheritance and Variance

Property types in PHP are strictly invariant. When extending a class, a child class cannot alter the type signature of a parent’s property in any way. It cannot widen (make less specific) or narrow (make more specific) the type. Furthermore, this invariance applies to untyped properties. If a parent class property is untyped, the child class property must also remain untyped. Attempting to add a type declaration to an inherited untyped property results in a fatal error.
class ParentClass {
    public $untypedValue;
    public int|float $typedValue;
}

class ChildClass extends ParentClass {
    // Fatal error: Type of ChildClass::$untypedValue must not be defined (as in class ParentClass)
    public int $untypedValue; 

    // Fatal error: Type of ChildClass::$typedValue must be int|float (as in class ParentClass)
    public int $typedValue; 
}

Unsupported Types

Certain types cannot be used as property types due to engine limitations or architectural constraints:
  • callable: Unsupported because the context of a callable (like self::method) depends on the scope where it is executed, which creates ambiguity when stored as a property.
  • void: Represents the absence of a return value and is conceptually invalid as a stored state.
  • never: Represents a function that does not return (exits or throws), which cannot be evaluated into a property value.
Master PHP with Deep Grasping Methodology!Learn More