strict_types en PHP: tipado estricto, type juggling y declare(strict_types=1)

PHP convierte tipos automáticamente cuando se lo permites: suma un string numérico a un entero, compara cosas que no son iguales y nadie dice nada. Esto se llama type juggling y puede ser el origen de bugs difíciles de rastrear. La directiva declare(strict_types=1) cambia ese comportamiento en el fichero donde la escribes: a partir de ese momento PHP exige que el tipo del argumento coincida exactamente con la firma de la función, o lanza un TypeError.

Qué hace declare(strict_types=1)

Puesta en la primera línea de un fichero PHP, antes de cualquier otro código, activa el modo estricto solo para ese fichero. Las llamadas que haga ese fichero a funciones con tipos declarados deben respetar exactamente esos tipos; PHP no intentará coercionar.

<?php
declare(strict_types=1);

function sumar(int $a, int $b): int {
    return $a + $b;
}

echo sumar(3, 4);      // 7 — correcto
echo sumar("3", 4);    // TypeError: Argument #1 must be of type int, string given

Sin strict_types, sumar("3", 4) devuelve 7 silenciosamente porque PHP convierte "3" a 3.

Type juggling: los casos que más sorprenden

El type juggling de PHP sigue reglas que pueden resultar contraintuitivas:

<?php
// Comparación laxa (==)
var_dump(0 == "foo");       // true en PHP 7, false en PHP 8
var_dump("1" == "01");      // true
var_dump("100" == "1e2");   // true (ambos son 100 en notación científica)
var_dump(0 == false);       // true
var_dump("" == false);      // true
var_dump("" == null);       // true

// Conversión implícita de string a entero
$total = 0;
$total += "42 artículos";   // $total = 42; PHP toma el prefijo numérico
$total += "artículos: 5";   // $total = 42; "artículos: 5" ? 0

Antes y después: cuatro ejemplos reales

Ejemplo 1: parseo de un parámetro de ruta

<?php
// SIN strict_types — silenciosamente acepta el string
function getUser(int $id): string {
    return "Usuario $id";
}

echo getUser("5abc");  // "Usuario 5" — PHP convierte "5abc" a 5, pierde "abc"

// CON strict_types=1 — TypeError inmediato
declare(strict_types=1);
echo getUser("5abc");  // Fatal error: TypeError

Ejemplo 2: función con float y string numérico

<?php
declare(strict_types=1);

function descuento(float $precio, float $porcentaje): float {
    return $precio * (1 - $porcentaje / 100);
}

// OK: los literales numéricos siempre son compatibles
echo descuento(100.0, 20.0);    // 80.0

// Error: un string "20.0" no es float en modo estricto
echo descuento(100.0, "20.0"); // TypeError

Ejemplo 3: valores booleanos disfrazados de enteros

<?php
declare(strict_types=1);

function activar(bool $estado): string {
    return $estado ? 'activo' : 'inactivo';
}

echo activar(true);   // activo
echo activar(1);      // TypeError en strict mode (1 no es bool)
echo activar(0);      // TypeError en strict mode (0 no es bool)

Ejemplo 4: retorno de tipo incorrecto

<?php
declare(strict_types=1);

function contarPalabras(string $texto): int {
    return str_word_count($texto);  // devuelve int, correcto
}

// str_word_count() SÍ devuelve int, por lo que funciona
echo contarPalabras("hola mundo"); // 2

Reglas importantes

  • El modo estricto afecta solo al fichero que lo declara, no a los ficheros que llama ni a los que lo incluyen.
  • Las funciones internas de PHP (como strlen(), array_map()…) son más tolerantes con la coerción incluso en modo estricto.
  • Los literales enteros y flotantes del propio código fuente siempre son del tipo correcto; el problema está en los datos externos (strings de formularios, APIs…).
  • Usar strict_types=1 no reemplaza la validación de entradas: sigue siendo necesario limpiar y validar los datos antes de pasarlos a tus funciones.

Cuándo activarlo

Activar strict_types=1 en todos los ficheros nuevos de un proyecto es una buena práctica. Los errores que antes fallaban silenciosamente aparecerán en desarrollo (con un TypeError claro) y no en producción con datos incorrectos. En código legado, actívalo fichero a fichero y corrige los TypeError que surjan: cada uno te muestra un punto donde antes perdías información de tipo sin darte cuenta.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP