CodeForge

TypeScript de Cero a Experto / Funciones e interfaces

Interfaces: contratos de objetos que se extienden

Teoría20 min20 XP

Ya describes formas de objetos con type. TypeScript tiene una segunda herramienta para lo mismo, con un sabor propio: interface. Nació para definir contratos de objetos y clases, y brilla en algo que type hace con más esfuerzo: extenderse y componerse. Hoy la conoces; en la próxima lección decides cuándo usar cuál.

El contrato de construcción

Declarar una interface

La sintaxis es casi igual a un type de objeto, pero sin el =:

interface.ts
interface Usuario {
id: number;
nombre: string;
apodo?: string;        // opcional, igual que en type
readonly creado: Date; // solo lectura, igual que en type
}

// se usa idéntico a un type:
function saludar(u: Usuario): string {
return "Hola, " + u.nombre;
}

const sara: Usuario = { id: 1, nombre: "Sara", creado: new Date() };

// las interfaces también describen métodos:
interface Repositorio {
guardar(dato: string): void;
cargar(id: number): string | undefined;
}

Para describir la forma de un objeto, interface Usuario { ... } y type Usuario = { ... } son casi intercambiables: mismos campos, mismos ? y readonly, mismos métodos. La diferencia aparece cuando quieres COMPONER contratos.

extends: componer contratos

Una interface puede heredar de otra (o de varias) con extends, sumando campos:

extends.ts
interface Entidad {
id: number;
creado: Date;
}

// Usuario ES una Entidad, MÁS sus propios campos:
interface Usuario extends Entidad {
nombre: string;
email: string;
}

// puede extender VARIAS a la vez:
interface ConTimestamps {
actualizado: Date;
}
interface Producto extends Entidad, ConTimestamps {
titulo: string;
precio: number;
}

const p: Producto = {
id: 1, creado: new Date(), actualizado: new Date(),   // de Entidad y ConTimestamps
titulo: "Café", precio: 4000,                          // propios
};

extends es la forma natural de las interfaces de decir "todo lo de aquellas, más esto". Componer Entidad + ConTimestamps + campos propios da un Producto completo sin repetir id ni creado. Es la herencia de contratos —limpia y legible—, y una de las razones por las que muchos prefieren interfaces para modelar jerarquías de datos.

Declaration merging: interfaces que se fusionan

Una capacidad EXCLUSIVA de las interfaces: si declaras dos con el mismo nombre, TS las FUSIONA en una sola. Suena raro, pero tiene un uso muy concreto:

merging.ts
interface Ventana {
titulo: string;
}
interface Ventana {
ancho: number;
}
// TS fusiona ambas → Ventana tiene titulo Y ancho:
const v: Ventana = { titulo: "Panel", ancho: 800 };

// ¿para qué sirve esto en la vida real? para EXTENDER tipos de librerías
// que no controlas. Ej: añadir una propiedad global a Window:
//   interface Window { miApp: { version: string } }
// ahora window.miApp está tipado en todo tu proyecto.

Estás escribiendo una librería y quieres que sus usuarios puedan AÑADIR campos a uno de tus tipos de configuración desde su propio código. ¿Qué herramienta lo permite?

Mini-reto

Compón contratos: 1) declara interface Animal { nombre: string; sonido(): string }; 2) crea interface Perro extends Animal { raza: string } y interface Gato extends Animal { independiente: boolean }; 3) escribe un objeto de cada uno, implementando el método sonido(), y llama sonido() sobre ambos. Sientes cómo extends arma jerarquías de datos sin repetir el contrato base.

Qué sigue

Tienes dos herramientas —type e interface— que se solapan casi por completo. La próxima lección zanja la pregunta que todo equipo debate: ¿cuál usar? Con una regla práctica simple que te deja decidir en un segundo, para siempre.