I'm using PHP 7.4.16. I enabled strict_types
in my PHP file thinking it would prevent passing a string
argument to a function expecting an int
by throwing a TypeError
. However, the function actually accepts the string
and coerces it to an int
. But if I place a return type hint on the function it works as expected, throwing a TypeError
.
This doesn't make sense to me and seems like a glaring inconsistency that can lead to bugs. Does anyone have any insight as to why this is or if I'm doing something wrong?
Test code:
<?php
declare(strict_types=1);
$ids = ['1', '2', '3'];
// No error thrown, coerces string argument to int.
array_map(fn (int $id) => $id, $ids);
// Throws PHP Fatal error: Uncaught TypeError: Return value of {closure}() must be of the type int, string returned
array_map(fn ($id): int => $id, $ids);
strict_types
only affects function calls within the file in which it's declared. From the PHP docs:
Note: Strict typing applies to function calls made from within the file with strict typing enabled, not to the functions declared within that file. If a file without strict typing enabled makes a call to a function that was defined in a file with strict typing, the caller's preference (coercive typing) will be respected, and the value will be coerced.
In your case, the examples are not calling the callback itself, they are passing it as an argument for array_map
, meaning that wherever the function array_map
is implemented, it has preference for coercive typing when array_map
is calling your callback.
A possible solution to this would be to wrap array_map
and make the call to your callback in a file in which strict_types is declared, such as this:
<?php
declare(strict_types=1);
$ids = ['1', '2', '3'];
function strict_array_map($fn, $arr){
return array_map(fn (...$arguments) => $fn(...$arguments), $arr);
}
// Now TypeError is thrown correctly
strict_array_map(fn (int $id) => $id, $ids);
// Throws PHP Fatal error: Uncaught TypeError: Return value of {closure}() must be of the type int, string returned
strict_array_map(fn ($id): int => $id, $ids);
https://www.php.net/manual/en/language.types.declarations.php#language.types.declarations.strict
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With