# Módulo 1 — Fundamentos y Sintaxis de TypeScript **Aplicación práctica: Sistema de gestión de recursos sanitarios (Humanos y materiales)** --- ## 1. Qué es ECMAScript ECMAScript es el **estándar que define el lenguaje JavaScript**, desarrollado por Ecma International. TypeScript es un **superset de JavaScript**, lo que significa que todo código JavaScript válido también es válido en TypeScript, pero añade **tipado estático**, decoradores y otras capacidades avanzadas. ```ts const nombre: string = 'Hospital Central'; console.log(`Bienvenido a la app de gestión de ${nombre}`); ``` --- ## 2. Qué es TypeScript TypeScript es un **lenguaje de programación fuertemente tipado y transpilado**. El código TypeScript se **compila a JavaScript**, permitiendo detectar errores **en tiempo de desarrollo**. Ventajas clave: * Tipado estático opcional * Mejor autocompletado y refactorización * Código más mantenible y escalable ```ts let usuario: string = 'María'; console.log(`Hola ${usuario}, bienvenida al sistema de gestión.`); let recursos: number = 10; let total: number = recursos * 2; console.log(`Total de recursos disponibles: ${total}`); ``` --- ## 3. Impresión por consola El objeto `console` funciona igual que en JavaScript, pero con mayor control gracias al tipado. ```ts interface RecursoResumen { tipo: string; cantidad: number; } const recursos: RecursoResumen[] = [ { tipo: 'Enfermeros', cantidad: 200 }, { tipo: 'Ambulancias', cantidad: 40 }, ]; console.log('Recursos actuales:'); console.info('Datos cargados correctamente.'); console.warn('Mascarillas por debajo del nivel recomendado.'); console.error('Error al conectar con la base de datos.'); console.table(recursos); ``` --- ## 4. Declaración de variables y modificadores de acceso En TypeScript se utilizan `let` y `const` (no se recomienda `var`). Además, **las clases sí soportan modificadores de acceso explícitos**: * `public` (por defecto) * `private` * `protected` * `readonly` ```ts type TipoRecurso = 'HUMANO' | 'MATERIAL'; class Recurso { private id: string; public unidad: string; public tipoRecurso: TipoRecurso; constructor(id: string, unidad: string, tipoRecurso: TipoRecurso) { this.id = id; this.unidad = unidad; this.tipoRecurso = tipoRecurso; } public mostrar(): void { console.log(`Recurso [id=${this.id}, tipo=${this.tipoRecurso}, unidad=${this.unidad}]`); } } const recurso = new Recurso('2jfn49cn2s8ad8cn2a2f342da', 'JMAPER', 'HUMANO'); recurso.mostrar(); ``` --- ## 5. Tipos primitivos TypeScript define explícitamente los tipos: ```ts let id: string = '12ERC7DFJG94KGLS045JD7'; let cantidad: number = 32; let activo: boolean = true; let unidad: undefined = undefined; let otrosDatos: null = null; ``` --- ## 6. Operadores Los operadores funcionan igual que en JavaScript, pero TypeScript evita combinaciones peligrosas mediante el tipado. ```ts console.log(10 + 5); console.log(10 / 3); console.log(10 % 3); ``` ```ts let enfermeros: number = 10; let ambulancias: number = 5; console.log(enfermeros > 0 && ambulancias > 0); console.log(!(enfermeros > 0)); ``` ```ts console.log(10 === 10); // true ``` --- ## 7. Arrays y genéricos Los arrays en TypeScript suelen ser **homogéneos** y tipados: ```ts interface RecursoInventario { id: string; unidad: string; tipoRecurso: TipoRecurso; } const recursos: RecursoInventario[] = [ { id: '18HFHSK2J3H123H412KH3', unidad: 'JMAPER', tipoRecurso: 'HUMANO' }, ]; const ambulancias: string[] = ['ET 101467', 'ET 101468', 'ET 101469']; ambulancias.push('ET 101470'); ambulancias.pop(); ambulancias.forEach(a => console.log(a)); ``` --- ## 8. Funciones Las funciones definen tipos de parámetros y retorno. ```ts function calcularAmbulanciasOperativas(total: number, inoperativas: number): number { return total - inoperativas; } ``` ### Parámetros por defecto ```ts function registrarRecurso( tipo: TipoRecurso = 'HUMANO', id: string = '1AJS8DF9J4GJ80DJS2NSJD', unidad: string = 'JMAPER' ): void { console.log(`Recurso: ${tipo}, Unidad: ${unidad}`); } ``` ### Funciones anidadas y ámbito ```ts function gestionarRecurso(): void { const tipo: TipoRecurso = 'MATERIAL'; function mostrarTipo(): void { console.log(`Tipo de recurso: ${tipo}`); } mostrarTipo(); } ``` ### Funciones flecha ```ts const reporteRecursos = (enfermeros: number, ambulancias: number): void => { console.log(`Enfermeros: ${enfermeros}, Ambulancias: ${ambulancias}`); }; ``` --- ## 9. Estructuras de control ```ts let ambulanciasDisponibles: number = 12; if (ambulanciasDisponibles > 0) { console.log('Hay ambulancias'); } else { console.log('No hay ambulancias disponibles'); } try { let resultado = ambulanciasDisponibles / 0; console.log(resultado); } catch (error) { console.error('Error en el cálculo', error); } const listaAmbulancias: string[] = ['ET 101467', 'ET 101468', 'ET 101469']; for (const amb of listaAmbulancias) { console.log(`Ambulancia: ${amb}`); } ``` --- ## 10. Clases, interfaces y objetos ### Interfaces ```ts interface RecursoDTO { id: string; unidad: string; tipoRecurso: TipoRecurso; } ``` De las interfaces pueden crearse objetos literales, que son objetos definidos *ad-hoc*: ```ts const recursoDTOEjemplo: RecursoDTO = { id: "21j5jshsy34js8skasu", unidad: "JMAPER", tipoRecurso: "MATERIAL" }; ``` ### Clases ```ts class RecursoEntidad { constructor( private id: string, public unidad: string, public tipoRecurso: TipoRecurso ) {} mostrar(): void { console.log(`Recurso [id=${this.id}, tipo=${this.tipoRecurso}, unidad=${this.unidad}]`); } } const datos: RecursoDTO = { id: '1j273hf83hd93j4f7gjd6', unidad: 'ACING', tipoRecurso: 'MATERIAL', }; const recursoEntidad = new RecursoEntidad(datos.id, datos.unidad, datos.tipoRecurso); recursoEntidad.mostrar(); ``` ## 10.1 Propiedades opcionales (`?`) y operador de aserción no nula (`!`) En sistemas reales (como un sistema de gestión sanitaria), **no todas las propiedades están siempre disponibles**. TypeScript permite modelar esta realidad de forma segura. ### Propiedades opcionales (`?`) El operador `?` indica que una propiedad **puede existir o no**. Internamente, TypeScript la trata como `tipo | undefined`. ```ts interface RecursoDetalle { id: string; unidad: string; tipoRecurso: TipoRecurso; observaciones?: string; // propiedad opcional } ``` Uso práctico: ```ts const recursoConObs: RecursoDetalle = { id: 'AJS829DJ2', unidad: 'JMAPER', tipoRecurso: 'MATERIAL', observaciones: 'Revisión pendiente', }; const recursoSinObs: RecursoDetalle = { id: 'KSI928DJ2', unidad: 'ACING', tipoRecurso: 'HUMANO', }; ``` Al acceder a una propiedad opcional, **TypeScript obliga a comprobar su existencia**: ```ts if (recursoConObs.observaciones) { console.log(recursoConObs.observaciones.toUpperCase()); } ``` Esto evita errores típicos de JavaScript en tiempo de ejecución. --- ### Operador de aserción no nula (`!`) El operador `!` se utiliza cuando **el desarrollador sabe que una propiedad existe**, aunque TypeScript no pueda deducirlo. > Es una forma de decirle al compilador: > **“Confía en mí, esta propiedad no es `null` ni `undefined` aquí.”** Ejemplo: ```ts class RecursoAsignado { public responsable?: string; asignar(responsable: string): void { this.responsable = responsable; } mostrarResponsable(): void { // TypeScript advierte que responsable podría ser undefined console.log(this.responsable!.toUpperCase()); } } ``` Uso: ```ts const recurso = new RecursoAsignado(); recurso.asignar('Dra. Martínez'); recurso.mostrarResponsable(); ``` Aquí: * `responsable` es opcional (`?`) * El operador `!` indica que **en este punto concreto** sí está definido --- ### Buenas prácticas importantes * `?` **modela incertidumbre real del dominio** * `!` **debe usarse con criterio**, solo cuando: * La lógica del programa garantiza la existencia * Ya se ha validado previamente * Un abuso de `!` puede ocultar errores reales Ejemplo correcto: ```ts if (recurso.responsable) { console.log(recurso.responsable.toUpperCase()); } ``` Ejemplo a evitar sin validación previa: ```ts console.log(recurso.responsable!.toUpperCase()); ``` ## 11. Otros objetos ### Date ```ts const fechaHoy: Date = new Date(); console.log('Fecha actual:', fechaHoy.toLocaleDateString()); const ultimaOperatividad: Date = new Date(2025, 9, 22); console.log('Última fecha de operatividad:', ultimaOperatividad.toLocaleDateString()); ``` ### Math ```ts console.log('Número aleatorio:', Math.random()); console.log('Redondeo hacia arriba:', Math.ceil(4.3)); console.log('Valor absoluto:', Math.abs(-5)); console.log('Máximo:', Math.max(10, 20, 5)); ``` ### type (Alias de tipos) La palabra clave `type` permite crear **alias de tipos**, facilitando la reutilización y la legibilidad del código. Es especialmente útil para **uniones**, **tipos compuestos** y **contratos simples**. ```ts type IDRecurso = string; type UnidadSanitaria = string; type Cantidad = number; type EstadoRecurso = 'OPERATIVO' | 'INOPERATIVO' | 'EN_MANTENIMIENTO'; ``` Uso práctico en el sistema: ```ts type RecursoBasico = { id: IDRecurso; unidad: UnidadSanitaria; estado: EstadoRecurso; }; const recursoBasico: RecursoBasico = { id: '7HG82JD92KS9', unidad: 'JMAPER', estado: 'OPERATIVO', }; ``` También pueden combinarse con interfaces: ```ts type RecursoCompleto = RecursoDTO & { estado: EstadoRecurso; fechaAlta: Date; }; ``` --- ### enum (Enumeraciones) Los `enum` permiten definir **conjuntos cerrados de valores**, mejorando la **seguridad semántica** frente a strings libres. ### Enum numérico ```ts enum NivelPrioridad { BAJA = 1, MEDIA, ALTA, CRITICA, } ``` ```ts const prioridadRecurso: NivelPrioridad = NivelPrioridad.ALTA; console.log('Nivel de prioridad:', prioridadRecurso); ``` ### Enum de strings (recomendado) ```ts enum EstadoOperativo { OPERATIVO = 'OPERATIVO', INOPERATIVO = 'INOPERATIVO', EN_MANTENIMIENTO = 'EN_MANTENIMIENTO', } ``` Uso en una clase: ```ts class RecursoEstado { constructor( public id: string, public estado: EstadoOperativo ) {} mostrarEstado(): void { console.log(`Recurso ${this.id} está ${this.estado}`); } } const recursoEstado = new RecursoEstado( 'AJD829DJ29', EstadoOperativo.EN_MANTENIMIENTO ); recursoEstado.mostrarEstado(); ``` --- ### Object ```ts const resumen = { humanos: 120, materiales: 340, }; console.log(Object.keys(resumen)); console.log(Object.values(resumen)); console.log(Object.entries(resumen)); ``` --- ### JSON Muy habitual en comunicaciones con APIs REST. ```ts const recursoJson = JSON.stringify(recursoBasico); console.log('JSON:', recursoJson); const recursoParseado = JSON.parse(recursoJson) as RecursoBasico; console.log('Objeto:', recursoParseado); ``` --- ### Set (colecciones sin duplicados) ```ts const unidades = new Set(); unidades.add('JMAPER'); unidades.add('ACING'); unidades.add('JMAPER'); // no se duplica console.log('Unidades sanitarias:', unidades); ``` --- ### Map (clave–valor tipado) ```ts const inventario = new Map(); inventario.set('Ambulancias', 40); inventario.set('Enfermeros', 200); console.log('Ambulancias:', inventario.get('Ambulancias')); ```