En este post veremos otros conceptos básicos que nos introduce TypeScript, como las uniones, los literales, los alias y las interfaces.
TypeScript introduce también otros tipos nuevos. Si vienes del artículo anterior ya lo sabes, en caso contrario son las tuplas, enums, any, unknown y never.
Uniones
Las uniones nos permiten combinar varios tipos de variable. Por ejemplo, esta función acepta un identificador que puede ser tanto un string como un número:
function imprimirId(id: string | number): void { console.log(`El identificador es ${id}`) } imprimirId("1") // correcto imprimirId(10) // correcto imprimir(true) // error
También podemos declarar variables que acepten únicamente unos valores concretos:
let tipoMensaje: "info" | "alerta" | "error" | number tipoMensaje = "alerta" // correcto tipoMensaje = "eror" // incorrecto tipoMensaje = 99 // correctoAunque las uniones nos proporcionan mucha flexibilidad, hemos de tener presente que deberemos ir con cuidado cuando usemos los métodos propios de strings o números, en este caso, como *length*, *indexOf*, *toUpperCase*, *toPrecision, toString*, etc.
Para poder usar estos tipos, deberemos asegurarnos antes qué tipo de variable estamos tratando:
function imprimirId(id: string | number): void { if (typeof id === "string") { console.log( `El identificador de texto es ${id} con ${id.length} caracteres` ) } else { console.log(`El identificador numérico es ${id}`) } } imprimirId("as@qwerty19") // El identificador de texto es as@qwerty19 con 11 caracteres imprimirId(10) // El identificador numérico es 10
Tipos literales
Podemos definir variables indicando tanto su tipo como el valor exacto que pueden contener:
const rol = "admin"
En este caso estamos indicando que la variable rol solo puede tener el valor admin. El tipo string se infiere. Esto, aunque parezca que no tenga mucho sentido ni utilidad, puede venir muy bien en las funciones usando los tipos literales junto a uniones:
function imprimeRol(rol: "user" | "admin") { console.log(rol) }
En este caso estamos indicando que el parámetro de entrada tiene que ser una cadena de texto, pero no cualquier cadena de texto, sino específicamente user o admin.
Alias de tipos
Los alias son una forma de crear tipos personalizados. Si vamos a usar un conjunto de tipos en múltiples lugares, podemos usar alias para referirnos a ellos y reutilizarlos.
type Usuario = { id: number nombre: string correo: string } function getCorreoUsuario(u: Usuario): string { return u.correo } function getIdUsuario(u: Usuario): number { return u.id }
Los tipos no tienen por qué ser necesariamente objetos como en el ejemplo, podemos definir tipos usando uniones o lo que nos convenga:
type ID = string | number
Con este ejemplo, podríamos usar el alias ID como tipo de variable:
function printId(id: ID) { // ... }
De este modo ID hace que el parámetro pueda ser o bien un string o bien un número. Esto puede resultar útil para ahorrarnos código si tenemos que reutilizar muchas veces alguna unión, pero es muy importante que le demos un nombre claro que no dificulte en ningún caso interpretar nuestras intenciones.
Interfaces
Muy parecido a los alias. Podemos usar exactamente el mismo ejemplo anterior y obtener el mismo resultado:
interface Usuario { id: number nombre: string correo: string } function getCorreoUsuario(u: Usuario): string { return u.correo } function getIdUsuario(u: Usuario): number { return u.id }
Fíjate que en el caso de la interfaz no ponemos el "=" justo después de su nombre. La diferencia con los alias es que estos últimos no son modificables. En otras palabras, si creamos un nuevo tipo con alias ya no podremos modificarlo, mientras que las interfaces son extendibles:
interface Usuario { id: number nombre: string correo: string } interface UsuarioAdmin extends Usuario { tokenApi: string } function getCorreoUsuario(u: Usuario): string { return u.correo } function getIdUsuario(u: Usuario): number { return u.id } function getTokenUsuarioAdmin(u: UsuarioAdmin): string { // aquí también podríamos acceder a los parámetros id, nombre y correo return u.tokenApi }
Deberemos determinar en cada caso si queremos usar alias o interfaces según nuestras necesidades.
Y esta ha sido la última parte de esta introducción a TypeScript. Puedes consultar este post con enlaces a cada parte por si quieres repasar conceptos.