Introducción: el eterno debate de los desarrolladores de TypeScript
Si alguna vez has escrito en TypeScript, seguramente te has enfrentado a la pregunta: "¿Cuándo usar interface y cuándo usar type?" Esta pregunta ha acumulado miles de visitas en Stack Overflow y se ha convertido en una verdadera piedra de tropiezo para los principiantes. Aclaremos de una vez por todas este dilema.
TypeScript es una extensión de JavaScript que añade tipado estático. Y tenemos dos herramientas principales para describir la estructura de datos: Interface y Type Alias. A primera vista hacen lo mismo, pero el diablo está en los detalles. En este artículo no solo enumeraremos las diferencias — las mostraremos con ejemplos reales y daremos recomendaciones claras.
¿Qué es Interface?
Interface es una forma de describir la estructura de un objeto. Es como un plano para los datos: le dices a TypeScript qué propiedades y métodos debe tener el objeto.
// Interfaz básicainterface User { name: string; age: number; email?: string; // propiedad opcional readonly id: number; // solo lectura}
// Usoconst user: User = { name: "Ana", age: 25, id: 1};Las interfaces pueden heredar unas de otras, lo que las hace ideales para describir jerarquías:
interface Animal { name: string; sound(): void;}
interface Dog extends Animal { breed: string; wagTail(): void;}
// Ahora Dog contiene todos los campos de Animal + los suyosconst myDog: Dog = { name: "Rex", breed: "Pastor Alemán", sound() { console.log("¡Guau!"); }, wagTail() { console.log("Mueve la cola"); }};¿Qué es Type Alias?
Type Alias (alias de tipo) es una herramienta más flexible. Puede describir no solo objetos, sino también primitivos, uniones e intersecciones de tipos.
// Tipo para un primitivotype ID = string | number;
// Tipo para un objetotype UserType = { name: string; age: number;};
// Tipo para una funcióntype Greeting = (name: string) => string;
// Union Type (unión)type Status = "active" | "inactive" | "pending";
// Intersection Type (intersección)type Person = { name: string };type Employee = Person & { salary: number };El superpoder principal de los tipos son los union types. Las interfaces no pueden hacer esto:
// ❌ Así no se puede con interface// interface Status = "active" | "inactive"; // ¡Error!
// ✅ ¡Con type es fácil!type Status = "active" | "inactive" | "pending";
function processStatus(status: Status) { switch (status) { case "active": console.log("Activo"); break; case "inactive": console.log("Inactivo"); break; case "pending": console.log("Pendiente"); break; }}Diferencias clave: Interface vs Type
Analicemos en detalle en qué se diferencian en la práctica.
1. Unión e intersección de tipos
Type soporta union (|) e intersection (&) directamente. Interface solo mediante extends.
// Union — solo typetype Success = { data: string };type Error = { error: string };type Result = Success | Error; // ¡Se puede!
// Intersectiontype Full = Success & Error; // ¡Se puede!
// Para interface habría que crear interfaces separadasinterface IResult extends Success, Error {} // Funciona, pero es engorroso2. Declaration merging (fusión de declaraciones)
Esta es una característica única de las interfaces. Si declaras dos interfaces con el mismo nombre, TypeScript las fusiona.
// Primera interfazinterface User { name: string;}
// Segunda interfaz con el mismo nombreinterface User { age: number;}
// Resultado: User = { name: string; age: number; }const user: User = {