Apariencia
📘 Clase 5 — Interfaces (Objetos y funciones)
TypeScript · 2026-07-12 · Carpeta:
02-Ejercicios/Interfaces⬅️ Volver al índice de clases
🎯 Qué aprendí
- Qué es una
interfacey cómo define la forma de un objeto. - Cómo tipar un objeto individual con una interfaz (
let persona: Persona). - Cómo tipar un array de objetos con
Persona[]. - Cómo declarar propiedades opcionales con
?. - Cómo usar una interface para describir la firma de una función.
- Por qué una interface es un contrato de tipos, no una clase instanciable.
- Propiedades de solo lectura con
readonly. - Cómo una interface extiende a otra (
extends) para reusar y ampliar forma.
📖 PARTE TEÓRICA
🧱 1. ¿Qué es una interface?
Una interface le dice a TypeScript qué forma debe tener un dato: qué propiedades existen, cuáles son obligatorias y qué tipo tiene cada una.
typescript
interface Persona {
nombre: string;
edad: number;
esDesarrollador: boolean;
}💡 Piensa en la interface como un molde o contrato: cualquier objeto que diga ser
Personadebe cumplir esa estructura.
👤 2. Tipar un objeto con una interface
Después de declarar la interface, puedes usarla como tipo:
typescript
let persona: Persona = {
nombre: "Styp",
edad: 30,
esDesarrollador: true
};Si falta una propiedad obligatoria, TypeScript avisa:
typescript
let personaIncompleta: Persona = {
nombre: "Ana"
// ❌ faltan edad y esDesarrollador
};🧪 Entrevista: ¿Qué ventaja da una interface? Autocompletado, validación de estructura, menos errores al escribir propiedades y código más claro.
📚 3. Arrays de objetos con Interface[]
También puedes usar la interface para tipar una lista completa:
typescript
let personas: Persona[] = [
{ nombre: "Styp", edad: 30, esDesarrollador: true },
{ nombre: "Juan", edad: 25, esDesarrollador: false },
{ nombre: "María", edad: 28, esDesarrollador: true }
];Eso significa que cada elemento del array debe cumplir la forma de Persona.
typescript
personas.push({ nombre: "Luis", edad: 26, esDesarrollador: false }); // ✅
personas.push({ nombre: "Luis" }); // ❌ faltan propiedades❓ 4. Propiedades opcionales con ?
Una propiedad opcional se marca con ?. Puede existir o no:
typescript
interface Persona {
nombre: string;
edad: number;
esDesarrollador: boolean;
lenguajeFavorito?: string;
}Ahora estos dos objetos son válidos:
typescript
let a: Persona = {
nombre: "Styp",
edad: 30,
esDesarrollador: true,
lenguajeFavorito: "TypeScript"
};
let b: Persona = {
nombre: "Juan",
edad: 25,
esDesarrollador: false
};💡
lenguajeFavorito?: stringequivale a decir que esa propiedad puede serstringo no existir (undefined).
🔁 5. Recorrer objetos tipados
Cuando recorres un array tipado, TypeScript ya sabe qué propiedades tiene cada objeto:
typescript
personas.forEach((personaActual) => {
console.log(personaActual.nombre);
if (personaActual.lenguajeFavorito) {
console.log(personaActual.lenguajeFavorito);
}
});📌 Dentro del
if, TS entiende quelenguajeFavoritosí existe, por eso te deja usarlo sin problema.
⚙️ 6. Interfaces para funciones
Una interface no solo sirve para objetos. También puede describir la firma de una función:
typescript
interface Sumar {
(a: number, b: number): number;
}Eso significa: "cualquier función de tipo Sumar debe recibir dos number y devolver un number".
typescript
let sumar: Sumar = (a: number, b: number): number => {
return a + b;
};Si intentas romper esa firma, TS lo detecta:
typescript
let sumarMal: Sumar = (a: string, b: string) => a + b;
// ❌ no coincide con la interface🚫 7. Interface vs clase
Una interface no se instancia. Esto no existe:
typescript
interface Persona {
nombre: string;
}
// let p = new Persona(); // ❌ ErrorLa interface solo vive en TypeScript para validar tipos. Al compilar a JavaScript, desaparece.
| Interface | Clase | |
|---|---|---|
| Define forma/contrato | ✅ | ✅ |
Se puede instanciar con new | ❌ | ✅ |
| Existe en JavaScript final | ❌ | ✅ |
| Tiene implementación real | ❌ | ✅ |
🧪 Entrevista: ¿Entonces para qué sirve una interface si desaparece? Para ayudarte mientras escribes: valida estructura, documenta el dato y evita errores antes de ejecutar.
🔒 8. Propiedades de solo lectura (readonly)
Una propiedad marcada con readonly se puede asignar solo una vez (al crear el objeto). Después, TypeScript bloquea cualquier reasignación:
typescript
interface Persona {
readonly nombre: string;
readonly edad: number;
readonly esDesarrollador: boolean;
}
let persona: Persona = { nombre: "Styp", edad: 30, esDesarrollador: true };
persona.nombre = "Otro";
// ❌ TS2540: Cannot assign to 'nombre' because it is a read-only property.| Propiedad normal | readonly | |
|---|---|---|
| Se puede leer | ✅ | ✅ |
| Se puede reasignar después de creado el objeto | ✅ | ❌ |
| Se define al momento de crear el objeto | ✅ | ✅ (obligatorio, no cambia luego) |
💡
readonlyes una protección solo en tiempo de compilación (como todainterface): en el JavaScript final no existe ningún bloqueo real, es TypeScript el que te avisa si intentas reasignar.
🧪 Entrevista: ¿
readonlyes lo mismo queconst? No.constevita reasignar la variable completa;readonlyevita reasignar una propiedad del objeto. Puedes tenerconst persona = {...}y aun así mutar sus propiedades si no sonreadonly.
🧬 9. Interfaces extendidas (extends)
Una interface puede heredar las propiedades de otra con extends, y agregar las suyas propias. Evita repetir la misma forma en varias interfaces:
typescript
interface Persona {
readonly nombre: string;
readonly edad: number;
readonly esDesarrollador: boolean;
}
interface Empleado extends Persona {
readonly puesto: string;
}
let empleado: Empleado = {
nombre: "Styp",
edad: 30,
esDesarrollador: true,
puesto: "Desarrollador Senior"
};Empleado debe cumplir todas las propiedades de Persona más las suyas (puesto). Si falta alguna heredada, TS también avisa.
📌
extendsentre interfaces es distinto aextendsentre clases: aquí solo se combinan formas (no hay lógica ni constructor de por medio), es puro contrato de tipos.
🧪 Entrevista: ¿Para qué sirve extender interfaces? Para modelar jerarquías de datos sin repetir propiedades:
Empleado,Cliente,Adminpueden compartir una basePersonay cada una sumar solo lo que le corresponde.
💻 PARTE PRÁCTICA
Archivos trabajados: 02-Ejercicios/Interfaces/interface.ts y interface2.ts
bash
cd 02-Ejercicios/Interfaces
tsc && node interface.js && node interface2.jsVerificado con:
- Una interface
Personapara objetos. - Un objeto
personatipado con esa interface. - Un array
personas: Persona[]. - Una propiedad opcional
lenguajeFavorito?. - Un recorrido con
forEach. - Una interface
Sumarpara una función. - Una interface
Direccioncon propiedad opcionalciudad?. - Una interface
Personacon propiedadesreadonly(bloquea reasignación). - Una interface
Empleado extends Persona(herencia entre interfaces).
Salida esperada:
text
Persona: { nombre: 'Styp', edad: 30, esDesarrollador: true, lenguajeFavorito: 'TypeScript' }
Personas: [...]
Nombre: Styp, Edad: 30, Es desarrollador: true
Lenguaje favorito: TypeScript
Nombre: Juan, Edad: 25, Es desarrollador: false
Nombre: María, Edad: 28, Es desarrollador: true
Lenguaje favorito: JavaScript
Suma: 15
Dirección: { calle: 'Calle Falsa', numero: 123, ciudad: 'Springfield' }
Persona Readonly: { nombre: 'Styp', edad: 30, esDesarrollador: true }
Empleado: { nombre: 'Styp', edad: 30, esDesarrollador: true, puesto: 'Desarrollador Senior' }Todo verificado y corriendo. ✅
🏋️ EJERCICIOS CON SOLUCIÓN
Ejercicio 1 — Interface Producto
Crea una interface Producto con nombre, precio y stock. Luego crea un objeto válido.
Ver solución
typescript
interface Producto {
nombre: string;
precio: number;
stock: number;
}
let producto: Producto = {
nombre: "Teclado",
precio: 120,
stock: 8
};
console.log(producto);Terminal esperada:
$ tsc producto.ts
$ node producto.js
{"nombre":"Teclado","precio":120,"stock":8}Ejercicio 2 — Propiedad opcional
Crea una interface Usuario con nombre obligatorio y telefono opcional.
Ver solución
typescript
interface Usuario {
nombre: string;
telefono?: string;
}
let usuario1: Usuario = { nombre: "Ana" };
let usuario2: Usuario = { nombre: "Luis", telefono: "999888777" };
console.log(usuario1);
console.log(usuario2);Terminal esperada:
$ tsc usuario.ts
$ node usuario.js
{ nombre: 'Ana' }
{ nombre: 'Luis', telefono: '999888777' }Ejercicio 3 — Array de objetos tipados
Crea una interface Curso y una lista con 2 cursos. Recorre la lista e imprime el nombre.
Ver solución
typescript
interface Curso {
nombre: string;
horas: number;
}
let cursos: Curso[] = [
{ nombre: "TypeScript", horas: 20 },
{ nombre: "Node.js", horas: 15 }
];
cursos.forEach((curso) => {
console.log(`Curso: ${curso.nombre}`);
});Terminal esperada:
$ tsc cursos.ts
$ node cursos.js
Curso: TypeScript
Curso: Node.jsEjercicio 4 — Interface de función
Crea una interface Multiplicar y una función arrow que la cumpla.
Ver solución
typescript
interface Multiplicar {
(a: number, b: number): number;
}
let multiplicar: Multiplicar = (a: number, b: number): number => {
return a * b;
};
console.log(multiplicar(4, 5)); // 20Terminal esperada:
$ tsc multiplicar.ts
$ node multiplicar.js
20Ejercicio 5 — Lista de empleados con propiedad opcional
Crea una interface Empleado con nombre, area, salario y correo?. Luego crea una lista con 3 empleados e imprime un resumen de cada uno. Si tiene correo, muéstralo; si no, imprime "Sin correo registrado".
Ver solución
typescript
interface Empleado {
nombre: string;
area: string;
salario: number;
correo?: string;
}
let empleados: Empleado[] = [
{ nombre: "Ana", area: "Frontend", salario: 2500, correo: "ana@empresa.com" },
{ nombre: "Luis", area: "Backend", salario: 2800 },
{ nombre: "Marta", area: "QA", salario: 2200, correo: "marta@empresa.com" }
];
empleados.forEach((empleado) => {
let correo = empleado.correo ? empleado.correo : "Sin correo registrado";
console.log(
`Nombre: ${empleado.nombre}, Área: ${empleado.area}, Salario: ${empleado.salario}, Correo: ${correo}`
);
});Terminal esperada:
$ tsc empleados.ts
$ node empleados.js
Nombre: Ana, Área: Frontend, Salario: 2500, Correo: ana@empresa.com
Nombre: Luis, Área: Backend, Salario: 2800, Correo: Sin correo registrado
Nombre: Marta, Área: QA, Salario: 2200, Correo: marta@empresa.comEjercicio 6 — Filtrar objetos tipados
Crea una interface Tarea con titulo, completada y prioridad. Luego crea una lista de tareas y filtra solo las que estén completadas.
Ver solución
typescript
interface Tarea {
titulo: string;
completada: boolean;
prioridad: number;
}
let tareas: Tarea[] = [
{ titulo: "Estudiar interfaces", completada: true, prioridad: 1 },
{ titulo: "Practicar arrays", completada: false, prioridad: 2 },
{ titulo: "Resolver ejercicios", completada: true, prioridad: 1 }
];
let tareasCompletadas: Tarea[] = tareas.filter((tarea) => tarea.completada);
tareasCompletadas.forEach((tarea) => {
console.log(`Tarea completada: ${tarea.titulo}`);
});Terminal esperada:
$ tsc tareas.ts
$ node tareas.js
Tarea completada: Estudiar interfaces
Tarea completada: Resolver ejerciciosEjercicio 7 — Interface de función con validación
Crea una interface EsMayorDeEdad para una función que reciba una edad y devuelva boolean. Después úsala para validar varias edades dentro de un array.
Ver solución
typescript
interface EsMayorDeEdad {
(edad: number): boolean;
}
let esMayorDeEdad: EsMayorDeEdad = (edad: number): boolean => {
return edad >= 18;
};
let edades: number[] = [15, 18, 21, 12, 30];
edades.forEach((edad) => {
console.log(`Edad: ${edad} → ¿Es mayor? ${esMayorDeEdad(edad)}`);
});Terminal esperada:
$ tsc mayorEdad.ts
$ node mayorEdad.js
Edad: 15 → ¿Es mayor? false
Edad: 18 → ¿Es mayor? true
Edad: 21 → ¿Es mayor? true
Edad: 12 → ¿Es mayor? false
Edad: 30 → ¿Es mayor? trueEjercicio 8 — Interface combinada en un caso más real
Crea una interface Estudiante con nombre, notas: number[] y activo. Luego:
- Crea una lista con 3 estudiantes.
- Recorre la lista.
- Calcula el promedio de notas de cada uno.
- Imprime si el estudiante está activo o inactivo.
Ver solución
typescript
interface Estudiante {
nombre: string;
notas: number[];
activo: boolean;
}
let estudiantes: Estudiante[] = [
{ nombre: "Carlos", notas: [15, 18, 20], activo: true },
{ nombre: "Lucía", notas: [12, 14, 16], activo: false },
{ nombre: "Pedro", notas: [19, 17, 18], activo: true }
];
estudiantes.forEach((estudiante) => {
let suma = estudiante.notas.reduce((acc, nota) => acc + nota, 0);
let promedio = suma / estudiante.notas.length;
let estado = estudiante.activo ? "Activo" : "Inactivo";
console.log(
`Estudiante: ${estudiante.nombre}, Promedio: ${promedio.toFixed(2)}, Estado: ${estado}`
);
});Terminal esperada:
$ tsc estudiantes.ts
$ node estudiantes.js
Estudiante: Carlos, Promedio: 17.67, Estado: Activo
Estudiante: Lucía, Promedio: 14.00, Estado: Inactivo
Estudiante: Pedro, Promedio: 18.00, Estado: ActivoEjercicio 9 — readonly + extends
Crea una interface Vehiculo con readonly placa: string y readonly marca: string. Luego crea Auto extends Vehiculo que agregue puertas: number. Crea un objeto Auto válido e intenta reasignar placa (comenta la línea y explica el error que da).
Ver solución
typescript
interface Vehiculo {
readonly placa: string;
readonly marca: string;
}
interface Auto extends Vehiculo {
puertas: number;
}
let auto: Auto = {
placa: "ABC-123",
marca: "Toyota",
puertas: 4
};
console.log(auto);
// auto.placa = "XYZ-999";
// ❌ TS2540: Cannot assign to 'placa' because it is a read-only property.Terminal esperada:
$ tsc auto.ts
$ node auto.js
{ placa: 'ABC-123', marca: 'Toyota', puertas: 4 }🧭 ¿Para qué se usa una interface?
Las interfaces se usan para dar estructura y claridad a los datos. En la práctica sirven muchísimo cuando empiezas a manejar objetos más grandes o repetidos.
- Para modelar objetos como
Persona,Producto,EmpleadooEstudiante. - Para tipar listas de objetos y evitar que se cuele un elemento con propiedades mal escritas.
- Para declarar propiedades opcionales, cuando algunos datos pueden venir o no.
- Para definir la firma de funciones, y así obligar a que reciban ciertos parámetros y devuelvan un tipo específico.
- Para documentar mejor el código: viendo la interface entiendes rápidamente qué forma tiene el dato.
- Para trabajar con datos de APIs, formularios, configuraciones, usuarios, productos, cursos, tareas y muchos otros casos reales.
💡 En resumen: una interface se usa cuando quieres que TypeScript te ayude a mantener el código ordenado, consistente y más fácil de entender.
❓ Preguntas y respuestas (autoevaluación)
1. ¿Qué es una interface en TypeScript?
Un contrato que define la forma de un dato: propiedades, tipos y, a veces, firmas de función.
2. ¿Cómo tipas un objeto con una interface?
let persona: Persona = { ... }.
3. ¿Cómo se tipa una lista de objetos con interface?
Con
Persona[],Producto[], etc.
4. ¿Qué hace ? en una propiedad de interface?
La vuelve opcional: puede existir o faltar.
5. ¿Una interface se puede instanciar con new?
No. No tiene implementación real; solo sirve para validar tipos.
6. ¿Una interface puede describir funciones?
Sí. Puede declarar la firma de una función, por ejemplo
(a: number, b: number): number.
7. ¿Qué diferencia hay entre interface y clase?
La interface describe; la clase describe y además implementa. La clase existe en JS, la interface no.
8. ¿Qué hace readonly en una propiedad?
Permite asignarla solo una vez (al crear el objeto). Reasignarla después es error de compilación (
TS2540), aunque en el JS final no hay ningún bloqueo real.
9. ¿readonly es lo mismo que const?
No.
constbloquea reasignar la variable completa;readonlybloquea reasignar una propiedad puntual de un objeto/interface.
10. ¿Qué hace interface B extends A?
Bhereda todas las propiedades deAy puede agregar las suyas. Un objeto de tipoBdebe cumplir la forma completa deAmás lo nuevo que declareB.
📎 Apuntes relacionados
➡️ Siguiente
type, unions e intersecciones para modelar datos de forma más flexible.