{ Adrian.Matías Quezada }

Tipos de identificación en Typescript

Aquí explico un concepto que encontré usando Typescript donde uno puede usar un tipo "string literal" con "union types" para crear nuevos tipos únicos.

Esto es particularmente útil para identificadores, los cuales (espero) nunca escribimos directamente en el código sino que son leídos de un programa externo y se pasan a otro componente intactos.

Digamos que tenemos dos tipos de entidades en nuestro programa: Usuario y Producto, y ambos tienen una propiedad id del tipo ObjectId. Nada previene que accidentalmente pasemos un ID de usuario donde se espera un ID de producto, solo un error en tiempo de ejecución que asustará a nuestros usuarios y robará nuestra paz mental. Creando distintos tipos para dichos IDs (como IdUsuario e IdProducto) podemos usar el poder de Typescript para asegurarnos que nunca los mezclamos accidentalmente.

// cualquier string sirve
type UserId = 'text-random-para-UserId';
type ProductId = 'text-random-para-ProductId';

function getUser(id: UserId) {}
function getProduct(id: ProductId) {}

const userId = '' as UserId;
const productId = '' as ProductId;

getUser(userId);
getUser(productId); // error
getUser(productId as UserId); // error

getProduct(productId);
getProduct(userId); // error
getProduct(userId as ProductId); // error

Este fue el enfoque que tomé en una herramenta para crear bots de Discord en deno llamada Denord, que usa distintos tipos de identificadores como GuildId (gremio), ChannelId y MessageId.

Actualización Julio 2022: Zack llevó esto un paso más allá creando una librería que esconde la parte desagradable de esta técnica https://github.com/modfy/nominal

Actualización Agosto 2023: Esto se está convirtiendo en un patrón común llamado branded types

(solo disponible en inglés 🇬🇧)