Lección 86 — Opcionales, Readonly e Index Signatures
🧠 Concepto
Section titled “🧠 Concepto”TypeScript ofrece tres herramientas fundamentales para refinar cómo se accede y modifica las propiedades de un objeto: opcionales, readonly e index signatures.
Propiedades opcionales (?)
Section titled “Propiedades opcionales (?)”Ya las vimos en lecciones anteriores. Marcan una propiedad que puede estar presente o no:
interface Config { url: string; puerto?: number; // opcional timeout?: number; // opcional}readonly
Section titled “readonly”Una propiedad readonly solo puede leerse, no reasignarse después de la inicialización:
interface Punto { readonly x: number; readonly y: number;}
const p: Punto = { x: 10, y: 20 };// p.x = 15; ❌ Error: Cannot assign to 'x' because it is a read-only propertyReadonlyArray y readonly en tuplas
Section titled “ReadonlyArray y readonly en tuplas”let numeros: ReadonlyArray<number> = [1, 2, 3];// numeros.push(4); ❌ Error// numeros[0] = 10; ❌ Error
let tupla: readonly [string, number] = ['Ana', 30];// tupla[0] = 'Luis'; ❌ ErrorIndex Signatures
Section titled “Index Signatures”Permiten definir objetos con propiedades dinámicas donde solo conoces el tipo de la clave y el valor:
interface Diccionario { [clave: string]: string;}
const traducciones: Diccionario = { hola: 'hello', adios: 'goodbye'};Combinación con interfaces
Section titled “Combinación con interfaces”Puedes mezclar propiedades fijas con index signatures:
interface UsuarioDinamico { nombre: string; edad: number; [extra: string]: unknown; // propiedades adicionales}
const usuario: UsuarioDinamico = { nombre: 'Ana', edad: 30, ciudad: 'Madrid', // ✅ permitido pais: 'España' // ✅ permitido};💻 Ejemplo
Section titled “💻 Ejemplo”// Objeto de configuración con opcionales y readonlyinterface ConfiguracionApp { readonly nombreApp: string; readonly version: string; puerto?: number; debug?: boolean; [key: string]: unknown;}
const config: ConfiguracionApp = { nombreApp: 'MiApp', version: '1.0.0', puerto: 3000, debug: true, dbHost: 'localhost', // propiedad dinámica dbPort: 5432 // propiedad dinámica};
// No se puede reasignar readonly// config.nombreApp = 'OtraApp'; ❌
// ReadonlyArrayconst inmovible: ReadonlyArray<string> = ['a', 'b', 'c'];// inmovible[0] = 'z'; ❌
// Index signature para cachéinterface Cache { [url: string]: { datos: unknown; timestamp: number; };}
const cache: Cache = { '/api/users': { datos: [], timestamp: Date.now() }, '/api/products': { datos: [], timestamp: Date.now() }};📝 Ejercicio
Section titled “📝 Ejercicio”Crea una interfaz Inventario con:
- Una propiedad
readonlyid: number. - Una propiedad opcional
nombre: string. - Una index signature
[codigo: string]: numberpara almacenar cantidades de productos.
Crea un objeto inventario, asigna algunos productos con cantidades, e intenta modificar el id para ver el error.
⚠️ Nota
Section titled “⚠️ Nota”Cuando combinas propiedades fijas con index signatures, la index signature debe ser compatible con todas las propiedades fijas. Por ejemplo, si tienes prop: string, la index signature debe ser [key: string]: string (no number).
Usa readonly en propiedades que representan identificadores o constantes de configuración que no deben cambiar después de la creación. Ayuda a prevenir mutaciones accidentales.