Typescript satisfies
Typescript 4.9 RC↗ fue anunciado a principio de mes y mi cambio favorito es el operador satisfies.
Este operador nos permite comprobar que un subtipo de un objeto o función esta incluido dentro de un supertipo dado, sin cambiar el tipo tipo del objeto o función original.
Por ejemplo, supongamos que definimos un tipo Color
y lo usamos para definir nuestro color favorito…
type Hex = string;
type RGB = { red: number; green: number; blue: number };
type Color = Hex | RGB;
const favoriteColor: Color = "#ffffff";
La variable favoriteColor
claramente tiene un valor de tipo Hex
, que a su ves es un string
, pero… ¿Que pasa si queremos pasar el valor a mayúsculas.
type Hex = string;
type RGB = { red: number; green: number; blue: number };
type Color = Hex | RGB;
const favoriteColor: Color = "#ffffff";
console.log(`Favorite color: ${favoriteColor.toUpperCase()}`);
A simple vista esto debería funcionar, pero dado que le dijimos a typescript que favoriteColor
es un Color
, y Color
puede ser de tipo Hex
o RGB
, entonces Typescript nos va a dar un error diciendo que Hex | RGB
no tiene la función toUpperCase
.
Hasta ahora, la manera de solucionar esto era haciendo un checkeo de tipos antes de usar la variable, o tiparla después de usarla.
type Hex = string;
type RGB = { red: number; green: number; blue: number };
type Color = Hex | RGB;
// Opción A: Hacer un checkeo de tipos
const favoriteColor: Color = "#ffffff";
if (typeof favoriteColor === "string") {
console.log(`Favorite color: ${favoriteColor.toUpperCase()}`);
}
// Option B: Tipar la variable después de usarla
const favoriteColor = "#ffffff";
const hexColor: Color = favoriteColor.toUpperCase();
Con el nuevo operador satisfies
podemos decirle a Typescript que valide que favoriteColor
es de tipo Color
, sin cambiar tipo de favoriteColor
.
type Hex = string;
type RGB = { red: number; green: number; blue: number };
type Color = Hex | RGB;
// Typescript valida que favoriteColor es un Color,
// pero el tipo de favoriteColor sigue siendo string.
const favoriteColor = "#ffffff" satisfies Color;
console.log(`Favorite color: ${favoriteColor.toUpperCase()}`);
De esta manera podemos operar con favoriteColor sabiendo que es un string
, y que cumple con Color
.
Si por algún motivo cambiáramos la definición de Color
para que solo soporte RGB
, entonces la validación daría un error.
type RGB = { red: number; green: number; blue: number };
type Color = RGB;
// Esto ya no cumple y da un error de compilación
const favoriteColor = "#ffffff" satisfies Color;
console.log(`Favorite color: ${favoriteColor.toUpperCase()}`);
Honestamente no se si agradecerle al equipo de Typescript por agregar esta funcionalidad, o putearlos por no haberla agregado antes.
En cualquiera de los dos casos, este tipo de funcionalidades son las que me trajeron a Typescript en un primer lugar, y me alegra que sigan innovando y mejorando la experiencia de los que lo usamos día a día.
-Andrés