Search code examples
phptypescastingfunction-signature

PHP type hinting is being ignored, no TypeError exception is thrown


I just debugged some PHP 7.1 code where I'd forgotten to remove a (bool) cast on the return value, but the function had a declared return type of int:

function get_foo(): int {
    $val = get_option('foo');
    return (bool) $val;
}

$foo = get_foo();

Test the code here.

It's easy to cast between bool and int, of course, but why didn't this throw a TypeError?

There are three scenarios where a TypeError may be thrown. ... The second is where a value being returned from a function does not match the declared function return type.

The same behaviour is exhibited for typed function parameters.

function get_foo(string $foo): int {
    $val = get_option($foo);
    return (bool) $val;
}

// no TypeError!
$foo = get_foo(34);

Solution

  • You need to add the strict_types directive for type hinting to work properly

    Quoting from PHP 7 New Features

    To enable strict mode, a single declare directive must be placed at the top of the file. This means that the strictness of typing for scalars is configured on a per-file basis. This directive not only affects the type declarations of parameters, but also a function's return type (see return type declarations, built-in PHP functions, and functions from loaded extensions.

    With that, you should do this.

    <?php
    declare(strict_types=1);
    
    function get_option_foo() : int {
        $val = get_option('foo'); // Returns a string that can be parsed as an int
        return (bool) $val;
    }
    
    $foo = get_option_foo();
    

    Try this once again, you will receive an Uncaught TypeError Exception