TypeScript de Cero a Experto / Funciones e interfaces
Interfaces: contratos de objetos que se extienden
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 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:
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:
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.