Arrivés avec PHP 7.0, les type hints permettent de vérifier le type d’une valeur.

function run_closure_if_something(Closure $closure)
{
    if (something()) {
        $closure();
    }
}

// Fatal error: Uncaught TypeError: Argument 1 passed to run_closure_if_something() must be an instance of Closure
say_hello_to_people('Wrong value.');

Quelle utilité ? Un type hint nous permet d’écrire moins de code. Plus besoin de vérifier le type du paramètre manuellement. Dans l’exemple ci-dessus, PHP nous renvoie une exception si une valeur autre qu’une instance de Closure a été passée. Cela revient au même que de la vérifier manuellement.

function run_closure_if_something($closure)
{
    if ($closure instanceof Closure && something()) {
        $closure();
    }

    throw new Exception('$closure must be an instance of "Closure".');
}

Les cas peu utiles

J’ai beaucoup de mal à comprendre le bénéfice de type hinter des valeurs avec des types facilement convertibles tels que int, float, string, bool, etc.

function sum(float $a, float $b)
{
    return $a + $b;
}

Quel intérêt ? Pourquoi ne pas s’en tenir au dynamisme de PHP afin de rendre l’expérience développeur plus agréable ?

function sum($a, $b)
{
    // On cast les valeurs et on ne se prend pas la tête.
    return (float) $a + (float) $b;
}
sum('1', 2); // 3
sum(3, 3.00); // 6

Autre exemple :

function say_hello_to_people($people)
{
    // On cast un éventuel string en array. Je trouve
    // ça simple et beau. Pas de complexité inutile.
    foreach ((array) $people as $person ) {
        echo "Hello, {$person}!";
    }
}

// Hello Homer!, Hello Marge, etc.
say_hello_to_people(['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie']);

// Hello, Moe!
say_hello_to_people('Moe');

Si le cast d’un type à un autre est impossible, PHP nous renverra une exception. C’est son job après tout.

L’abus des type hints et le refactoring

Refactorer son code est important. Lorsqu’on abuse des type hints, cela devient beaucoup plus fastidieu. Admettons qu’on ait type hinté une valeur à int, un peu partout dans le code, mais qu'on veuille désormais la passer à string ? C'est incroyablement barbant. Personnellement, j'en suis arrivé à la conclusion qu'un type hint de ce genre est totalement inutile. Omettez-le, et vous verrez comme votre vie en sera simplifiée.

Type hinter les valeurs de retour

function sum($a, $b) : float
{
    // On cast les valeurs et on ne se prend pas la tête.
    return (float) $a + (float) $b;
}

Là encore, l’intérêt est inexistant. A partir du moment où votre code est bien testé, il n’y a aucun besoin de vérifier le type de la valeur de retour d’une fonction. Dans le cas où vous souhaitez seulement documenter votre code, utilisez plutôt du DocBlock.

/**
 * Return the sum of two given numbers.
 *
 * @param  mixed $a
 * @param  mixed $b
 *
 * @return float Sum of A and B.
 */
function sum($a, $b)
{
    return (float) $a + (float) $b;
}

Quid des performances ?

Contrairement à ce que l’ont pourrait croire, le type hinting dégrade les performances de votre code (de manière insignifiante, sauf si appliqué à très grande échelle), car le type de votre valeur est vérifié au runtime (PHP est fondamentalement un langage dynamique). De ce fait, je trouve qu’il est judicieux de limiter son utilisation à un réel besoin de vérifier le type d’une valeur, ou pour aider (par exemple) le service container de Laravel qui est basé sur la Reflection.