Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Type Parametricity

Type parametricity, or parametric polymorphism, is the ability to write a function, class, or interface once and have it work uniformly over any type, with that type supplied as a parameter rather than hard-coded. list<Order> and array<string, Money> describe the same shape as list<Animal>: only the type parameter changes, the code that manipulates the list does not.

PHP has no native syntax for this. Every type declaration the engine understands, from class types to scalar types to DNF types, is checked at runtime, and a naive generics implementation would either need a full compilation step that verifies the parameter before execution, as Java and TypeScript do through type erasure, or it would need to check the parameter at every access, which the engine does not currently do.

In practice, PHP code expresses type parametricity today through a docblock type language, interpreted by tools such as PHPStan and Psalm rather than by the engine: @param list<Order> $orders. This delivers most of the benefit of generics without a language change, at the cost of the check happening in a separate tool instead of the runtime. Proposals such as bound-erased generic types tried to bring the syntax into the language without the runtime check and were declined for breaking the invariant that a PHP type declaration is always enforced; a gradual, runtime-checked path starting with invariant type parameters on interfaces is being explored instead.

<?php

    /**
     * @param list<Order> $orders
     * @return Money
     */
    function total(array $orders): Money
    {
        return array_reduce($orders, fn (Money $sum, Order $o) => $sum->add($o->total()), Money::zero());
    }

?>

Documentation

See Also