Union Types
Los Union Types permiten declarar que un parametro, propiedad o
retorno puede ser de varios tipos, usando la sintaxis tipo1|tipo2.
Sintaxis basica
Usa el caracter | para separar los tipos permitidos:
<?php
declare(strict_types=1);
// Parametro que acepta int o float
function calcularDescuento(int|float $precio, int $porcentaje): float
{
return $precio * (1 - $porcentaje / 100);
}
echo calcularDescuento(100, 20); // 80
echo calcularDescuento(99.99, 10); // 89.991
// Retorno que puede ser string o false
function buscarUsuario(int $id): string|false
{
$usuarios = [1 => 'Ana', 2 => 'Luis'];
return $usuarios[$id] ?? false;
}
$resultado = buscarUsuario(1); // 'Ana'
$resultado = buscarUsuario(99); // false
Tipos nullables
Puedes incluir null en un union type. Es equivalente
a usar ?tipo pero mas explicito:
<?php
declare(strict_types=1);
class Usuario
{
public function __construct(
public string $nombre,
public string|null $telefono = null // Equivale a ?string
) {}
}
// Con mas de dos tipos, debes usar union
function procesar(string|int|null $valor): void
{
if ($valor === null) {
echo 'Sin valor';
} elseif (is_string($valor)) {
echo "Texto: $valor";
} else {
echo "Numero: $valor";
}
}
procesar('hola'); // Texto: hola
procesar(42); // Numero: 42
procesar(null); // Sin valor
Union types en propiedades
<?php
declare(strict_types=1);
class Configuracion
{
// La propiedad puede ser string, int, bool o array
public string|int|bool|array $valor;
public function __construct(string|int|bool|array $valor)
{
$this->valor = $valor;
}
}
$config1 = new Configuracion('localhost');
$config2 = new Configuracion(8080);
$config3 = new Configuracion(true);
$config4 = new Configuracion(['host' => 'localhost', 'port' => 8080]);
El tipo false
PHP 8 permite usar false como tipo en unions,
util para funciones que retornan false en caso de error:
<?php
declare(strict_types=1);
function encontrarIndice(array $items, mixed $buscar): int|false
{
$indice = array_search($buscar, $items, true);
return $indice; // int si encuentra, false si no
}
$colores = ['rojo', 'verde', 'azul'];
$resultado = encontrarIndice($colores, 'verde');
if ($resultado !== false) {
echo "Encontrado en posicion: $resultado"; // 1
}
$resultado = encontrarIndice($colores, 'amarillo');
if ($resultado === false) {
echo 'No encontrado';
}
Intersection types (PHP 8.1)
PHP 8.1 introduce intersection types con &, que requieren
que el valor implemente TODOS los tipos:
<?php
declare(strict_types=1);
interface Serializable
{
public function serializar(): string;
}
interface Validable
{
public function esValido(): bool;
}
// El parametro debe implementar AMBAS interfaces
function guardar(Serializable&Validable $objeto): void
{
if ($objeto->esValido()) {
$datos = $objeto->serializar();
echo "Guardando: $datos";
}
}
class Documento implements Serializable, Validable
{
public function __construct(private string $contenido) {}
public function serializar(): string
{
return json_encode(['contenido' => $this->contenido]);
}
public function esValido(): bool
{
return strlen($this->contenido) > 0;
}
}
guardar(new Documento('Hola mundo'));
Ejercicios
Ejercicio 1: Funcion formatear
Crea una funcion formatear que reciba int|float|string
y retorne siempre un string formateado.
Ver solucion
<?php
declare(strict_types=1);
function formatear(int|float|string $valor): string
{
if (is_int($valor)) {
return "Entero: $valor";
}
if (is_float($valor)) {
return 'Decimal: ' . number_format($valor, 2);
}
return "Texto: $valor";
}
echo formatear(42); // Entero: 42
echo formatear(3.14159); // Decimal: 3.14
echo formatear('hola'); // Texto: hola
Ejercicio 2: Clase Respuesta
Crea una clase Respuesta con una propiedad datos
que pueda ser array|string|null y un metodo que
indique si tiene datos.
Ver solucion
<?php
declare(strict_types=1);
class Respuesta
{
public function __construct(
public array|string|null $datos = null
) {}
public function tieneDatos(): bool
{
if ($this->datos === null) {
return false;
}
if (is_array($this->datos)) {
return count($this->datos) > 0;
}
return strlen($this->datos) > 0;
}
}
$r1 = new Respuesta(['id' => 1]);
$r2 = new Respuesta(null);
echo $r1->tieneDatos(); // true
echo $r2->tieneDatos(); // false
¿Has encontrado un error o tienes una sugerencia?
Escribenos