miércoles, 25 de junio de 2025

Reflexión Avanzada de Tipos de Retorno en PHP 8+

Reflexión Avanzada de Tipos de Retorno en PHP 8+

PHP 8 introdujo mejoras significativas en la inferencia y declaración de tipos, lo que permite un análisis más profundo del código en tiempo de ejecución mediante la API de Reflection. Este post explora cómo podemos aprovechar la reflexión para examinar los tipos de retorno de métodos y funciones, incluyendo tipos de unión (union types) y tipos intersectados (intersection types, disponibles a partir de PHP 8.1), así como el tipo de retorno "never".


<?php

declare(strict_types=1);

class Ejemplo
{
    public function obtenerValor(): int|string
    {
        return rand(0, 1) ? 123 : "cadena";
    }

    public function nuncaRetorna(): never
    {
        throw new \Exception("Esta función nunca retorna.");
    }

    public function siempreDevuelveAlgo(): object&DateTimeInterface {
        return new DateTime();
    }
}

$reflection = new ReflectionMethod(Ejemplo::class, 'obtenerValor');
$returnType = $reflection->getReturnType();

if ($returnType instanceof ReflectionUnionType) {
    echo "El tipo de retorno es una unión de tipos:\n";
    foreach ($returnType->getTypes() as $type) {
        echo "  - " . $type->getName() . "\n";
    }
} else {
    echo "El tipo de retorno no es una unión.\n";
}

$reflectionNever = new ReflectionMethod(Ejemplo::class, 'nuncaRetorna');
$returnTypeNever = $reflectionNever->getReturnType();

if ($returnTypeNever instanceof ReflectionNamedType && $returnTypeNever->getName() === 'never') {
    echo "Esta función declara un tipo de retorno 'never'.\n";
}

$reflectionIntersection = new ReflectionMethod(Ejemplo::class, 'siempreDevuelveAlgo');
$returnTypeIntersection = $reflectionIntersection->getReturnType();

if ($returnTypeIntersection instanceof ReflectionIntersectionType) {
    echo "El tipo de retorno es una intersección de tipos:\n";
    foreach ($returnTypeIntersection->getTypes() as $type) {
        echo "  - " . $type->getName() . "\n";
    }
}

El código anterior demuestra cómo utilizar ReflectionMethod para obtener el tipo de retorno de un método. Para tipos de unión, getReturnType() retorna una instancia de ReflectionUnionType, que permite iterar sobre los tipos individuales que componen la unión. De forma similar, para tipos de intersección se usa ReflectionIntersectionType. El código también muestra cómo detectar si una función tiene un tipo de retorno 'never'.


<?php

function ejemploFuncion(int $a, string $b): array {
    return [$a, $b];
}

$reflectionFunction = new ReflectionFunction('ejemploFuncion');
$returnType = $reflectionFunction->getReturnType();

if ($returnType instanceof ReflectionNamedType) {
    echo "El tipo de retorno de la función es: " . $returnType->getName() . "\n";
}
    

Este segundo ejemplo muestra cómo se puede usar ReflectionFunction para obtener el tipo de retorno de una función global. Es importante recordar que la reflexión requiere que el tipo de retorno esté explícitamente declarado en la firma de la función o método para que pueda ser determinado correctamente.

En conclusión, la API de Reflection en PHP 8 y versiones posteriores ofrece potentes herramientas para analizar los tipos de retorno en tiempo de ejecución, lo cual es especialmente útil para generar documentación automatizada, validar el código en tiempo de ejecución o construir frameworks que se adapten dinámicamente a los tipos de datos.

No hay comentarios:

Publicar un comentario