Saltar al contenido principal
Volver atrás

TypeScript #3: Objetos e Interfaces

#typescript #objects #interfaces

Cómo dar forma a tus datos. Interfaces, Types y por qué "any" es tu enemigo.

Hasta ahora hemos visto tipos primitivos (string, number, boolean). Pero el mundo real funciona con objetos. Usuarios, Productos, Pedidos… todos son objetos con múltiples propiedades.

La Anarquía de los Objetos Anónimos

En JavaScript puro, solemos pasar objetos de un lado a otro confiando en nuestra memoria.

javascript
function imprimirUsuario(usuario) {
  // 🤞 Esperemos que 'usuario' tenga estas propiedades...
  console.log("Nombre: " + usuario.name.toUpperCase());
  console.log("Edad: " + usuario.age);
}

// Un mes después, alguien llama a la función así:
imprimirUsuario({ nombre: "Alice", edad: 30 }); 
// 💥 CRASH: Cannot read properties of undefined (reading 'toUpperCase')
// ¿Por qué? Porque pasamos "nombre" en español pero la función esperaba "name" en inglés.

TypeScript evita esto obligándonos a definir la FORMA (Shape) de nuestros objetos.

Interfaces: El Contrato

Una interface es como un contrato. Si un objeto dice ser un Usuario, DEBE cumplir el contrato.

typescript
interface Usuario {
  name: string;
  age: number;
  isDeveloper: boolean;
}

const alice: Usuario = {
  name: "Alice",
  age: 39,
  isDeveloper: true
}; // ✅ Cumple el contrato

const pepe: Usuario = {
  name: "Pepe"
}; // ❌ Error: Faltan las propiedades 'age' e 'isDeveloper'

Propiedades Opcionales (?)

A veces no tenemos todos los datos. Quizás el email es opcional. Para eso usamos el signo de interrogación ? después del nombre de la propiedad.

typescript
interface Producto {
  id: number;
  nombre: string;
  descripcion?: string; // 👈 Opcional (string | undefined)
}

const mesa: Producto = {
  id: 1,
  nombre: "Mesa de escritorio"
  // No hace falta poner descripción
};

Propiedades de Solo Lectura (readonly)

Si queremos asegurarnos de que una propiedad nunca cambie después de crear el objeto (como un ID), usemos readonly.

typescript
interface Configuracion {
  readonly apiKey: string;
  theme: "light" | "dark";
}

const config: Configuracion = {
  apiKey: "xyz-123",
  theme: "light"
};

config.theme = "dark"; // ✅ Puedes cambiarlo
config.apiKey = "abc-999"; // ❌ Error: Cannot assign to 'apiKey' because it is a read-only property.

¿type vs interface?

Veremos gente usando type Usuario = { ... } en lugar de interface Usuario { ... }. Para definir la forma de un objeto, ambos funcionan casi igual.

Regla de oro (por ahora):

  • Usemos interface para definir objetos que representan entidades (Usuario, Post, Producto).
  • Usemos type para Uniones (string | number), primitivos o tuplas.

En la Parte 8 profundizaremos en las diferencias técnicas, pero por ahora quedémonos con eso.

¡Intentémoslo!

Vamos a poner a prueba lo aprendido. Tenemos que definir una interfaz y crear un objeto específico para pasar la validación.

Requisitos del ejercicio:

  1. Definamos una interfaz llamada Videojuego con:
    • titulo (string)
    • anio (number) — Usamos anio para evitar la ñ en código.
    • plataforma (opcional, string)
  2. Creemos un objeto constante llamado juegoFavorito que implemente esa interfaz.
  3. Los datos deben ser exactamente: “The Legend of Zelda”, año 1986.
¡Ey!

Probemos a activar el volumen del editor antes de darle al botón > Run cuando vayamos a resolver el ejercicio!

En la Parte 4, veremos qué pasa cuando tenemos muchos objetos iguales… es decir, Arrays.