|
|
|
# Módulo 2 — Importación de elementos en JavaScript (Adaptado a tu API)
|
|
|
|
# Módulo 2 — Importación de elementos en TypeScript
|
|
|
|
|
|
|
|
## 1. Importación de datos
|
|
|
|
|
|
|
|
En JavaScript es posible importar datos (constantes, variables, objetos o listas) definidos en otros archivos, o bien cargarlos desde archivos JSON externos.
|
|
|
|
Esto permite mantener la información organizada y separada de la lógica del programa.
|
|
|
|
TypeScript utiliza el **sistema de módulos ES** igual que JavaScript, pero añade **tipado explícito**, lo que permite validar la estructura de los datos en tiempo de desarrollo.
|
|
|
|
|
|
|
|
En este módulo, los ejemplos se adaptan a la estructura real de tu API: recursos humanos, recursos materiales y activaciones.
|
|
|
|
En este módulo los ejemplos se adaptan a la estructura real de tu API: **recursos humanos, recursos materiales y activaciones**.
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
### Ejemplo: Importación desde otro archivo JavaScript
|
|
|
|
### Ejemplo: Importación desde otro archivo TypeScript
|
|
|
|
|
|
|
|
Archivo `data/recursos.js`:
|
|
|
|
Archivo `data/recursos.ts`:
|
|
|
|
|
|
|
|
```js
|
|
|
|
// data/recursos.js
|
|
|
|
export const recursosHumanos = [
|
|
|
|
```ts
|
|
|
|
// data/recursos.ts
|
|
|
|
export type TipoRecurso = 'Humano' | 'Material';
|
|
|
|
|
|
|
|
export interface RecursoBase {
|
|
|
|
id: number;
|
|
|
|
nombreRecurso: string;
|
|
|
|
tipoRecurso: TipoRecurso;
|
|
|
|
unidad: string;
|
|
|
|
comunidadAutonoma: string;
|
|
|
|
provincia: string;
|
|
|
|
localidad: string;
|
|
|
|
base: string;
|
|
|
|
servicioMedicoReferencia?: string; // opcional
|
|
|
|
}
|
|
|
|
|
|
|
|
export const recursosHumanos: RecursoBase[] = [
|
|
|
|
{
|
|
|
|
id: 1,
|
|
|
|
nombreRecurso: 'Laura Gómez',
|
| ... | ... | @@ -35,12 +48,12 @@ export const recursosHumanos = [ |
|
|
|
comunidadAutonoma: 'Madrid',
|
|
|
|
provincia: 'Madrid',
|
|
|
|
localidad: 'Pozuelo de Alarcón',
|
|
|
|
base: 'General Cavalcanti.',
|
|
|
|
base: 'General Cavalcanti',
|
|
|
|
servicioMedicoReferencia: 'Hospital Infanta Sofía',
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
export const recursosMateriales = [
|
|
|
|
export const recursosMateriales: RecursoBase[] = [
|
|
|
|
{
|
|
|
|
id: 10,
|
|
|
|
nombreRecurso: 'ET 117928',
|
| ... | ... | @@ -64,40 +77,30 @@ export const recursosMateriales = [ |
|
|
|
];
|
|
|
|
```
|
|
|
|
|
|
|
|
Archivo `gestion/mostrarRecursos.js`:
|
|
|
|
Archivo `gestion/mostrarRecursos.ts`:
|
|
|
|
|
|
|
|
```js
|
|
|
|
// gestion/mostrarRecursos.js
|
|
|
|
import { recursosHumanos, recursosMateriales } from '../data/recursos.js';
|
|
|
|
```ts
|
|
|
|
// gestion/mostrarRecursos.ts
|
|
|
|
import { recursosHumanos, recursosMateriales, RecursoBase } from '../data/recursos';
|
|
|
|
|
|
|
|
console.log('Listado de recursos humanos:');
|
|
|
|
recursosHumanos.forEach((r) => {
|
|
|
|
recursosHumanos.forEach((r: RecursoBase) => {
|
|
|
|
console.log(`- ${r.nombreRecurso} (${r.unidad})`);
|
|
|
|
});
|
|
|
|
|
|
|
|
console.log('\nListado de recursos materiales:');
|
|
|
|
recursosMateriales.forEach((r) => {
|
|
|
|
recursosMateriales.forEach((r: RecursoBase) => {
|
|
|
|
console.log(`- ${r.nombreRecurso} [${r.base}]`);
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
**Salida esperada:**
|
|
|
|
|
|
|
|
```
|
|
|
|
Listado de recursos humanos:
|
|
|
|
- Laura Gómez (AGRUSAN)
|
|
|
|
- Javier Ruiz (NAS 11)
|
|
|
|
|
|
|
|
Listado de recursos materiales:
|
|
|
|
- ET 117928 [General Cavalcanti]
|
|
|
|
- ET 117929 [General Cavalcanti]
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
### Ejemplo: Importación desde un archivo JSON usando fetch()
|
|
|
|
### Ejemplo: Importación desde un archivo JSON
|
|
|
|
|
|
|
|
Archivo `data/activaciones.json`:
|
|
|
|
En TypeScript, los datos JSON suelen mapearse a **interfaces**.
|
|
|
|
|
|
|
|
Archivo `data/activaciones.json` (sin cambios):
|
|
|
|
|
|
|
|
```json
|
|
|
|
[
|
| ... | ... | @@ -109,24 +112,32 @@ Archivo `data/activaciones.json`: |
|
|
|
"tipoJornada": "COMPLETA",
|
|
|
|
"tipoSituacion": "ACTIVIDAD",
|
|
|
|
"observaciones": "Servicio programado"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"id": 101,
|
|
|
|
"recursoId": 10,
|
|
|
|
"fechaHoraInicio": "2025-01-05T09:30:00",
|
|
|
|
"fechaHoraFin": "2025-01-05T12:00:00",
|
|
|
|
"tipoJornada": "PARCIAL",
|
|
|
|
"tipoSituacion": "NO_OPERATIVO",
|
|
|
|
"observaciones": "Revisión mecánica"
|
|
|
|
}
|
|
|
|
]
|
|
|
|
```
|
|
|
|
|
|
|
|
Archivo `gestion/activaciones.js`:
|
|
|
|
Archivo `models/Activacion.ts`:
|
|
|
|
|
|
|
|
```ts
|
|
|
|
// models/Activacion.ts
|
|
|
|
export interface Activacion {
|
|
|
|
id: number;
|
|
|
|
recursoId: number;
|
|
|
|
fechaHoraInicio: string;
|
|
|
|
fechaHoraFin: string;
|
|
|
|
tipoJornada: 'COMPLETA' | 'PARCIAL';
|
|
|
|
tipoSituacion: 'ACTIVIDAD' | 'NO_OPERATIVO';
|
|
|
|
observaciones?: string;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Archivo `gestion/activaciones.ts`:
|
|
|
|
|
|
|
|
```js
|
|
|
|
// gestion/activaciones.js
|
|
|
|
async function cargarActivaciones() {
|
|
|
|
```ts
|
|
|
|
// gestion/activaciones.ts
|
|
|
|
import { Activacion } from '../models/Activacion';
|
|
|
|
|
|
|
|
async function cargarActivaciones(): Promise<void> {
|
|
|
|
try {
|
|
|
|
const respuesta = await fetch('../data/activaciones.json');
|
|
|
|
|
| ... | ... | @@ -134,45 +145,33 @@ async function cargarActivaciones() { |
|
|
|
throw new Error(`Error al cargar los datos: ${respuesta.status}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
const activaciones = await respuesta.json();
|
|
|
|
const activaciones: Activacion[] = await respuesta.json();
|
|
|
|
|
|
|
|
console.log('Activaciones registradas:');
|
|
|
|
activaciones.forEach((a) => {
|
|
|
|
console.log(
|
|
|
|
`- Activación #${a.id}: recurso ${a.recursoId} ` + `(${a.tipoSituacion}, ${a.tipoJornada})`
|
|
|
|
);
|
|
|
|
activaciones.forEach((a: Activacion) => {
|
|
|
|
console.log(`- Activación #${a.id}: recurso ${a.recursoId} (${a.tipoSituacion}, ${a.tipoJornada})`);
|
|
|
|
});
|
|
|
|
} catch (error) {
|
|
|
|
console.error('No se pudieron cargar las activaciones:', error.message);
|
|
|
|
console.error('No se pudieron cargar las activaciones', error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cargarActivaciones();
|
|
|
|
```
|
|
|
|
|
|
|
|
**Salida esperada:**
|
|
|
|
|
|
|
|
```
|
|
|
|
Activaciones registradas:
|
|
|
|
- Activación #100: recurso 1 (ACTIVIDAD, COMPLETA)
|
|
|
|
- Activación #101: recurso 10 (NO_OPERATIVO, PARCIAL)
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 2. Importación de funciones
|
|
|
|
|
|
|
|
Ejemplo adaptado a métricas reales: porcentaje de recursos en situación de actividad.
|
|
|
|
|
|
|
|
Archivo `utils/calculos.js`:
|
|
|
|
Archivo `utils/calculos.ts`:
|
|
|
|
|
|
|
|
```js
|
|
|
|
// utils/calculos.js
|
|
|
|
export function calcularPorcentajeActividad(total, enActividad) {
|
|
|
|
```ts
|
|
|
|
// utils/calculos.ts
|
|
|
|
export function calcularPorcentajeActividad(total: number, enActividad: number): string {
|
|
|
|
return ((enActividad / total) * 100).toFixed(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function formatearSituacion(situacion) {
|
|
|
|
export function formatearSituacion(situacion: string): string {
|
|
|
|
return situacion
|
|
|
|
.toLowerCase()
|
|
|
|
.replace('_', ' ')
|
| ... | ... | @@ -180,63 +179,53 @@ export function formatearSituacion(situacion) { |
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Archivo `reportes/actividadRecursos.js`:
|
|
|
|
Archivo `reportes/actividadRecursos.ts`:
|
|
|
|
|
|
|
|
```js
|
|
|
|
// reportes/actividadRecursos.js
|
|
|
|
import { calcularPorcentajeActividad, formatearSituacion } from '../utils/calculos.js';
|
|
|
|
```ts
|
|
|
|
// reportes/actividadRecursos.ts
|
|
|
|
import { calcularPorcentajeActividad, formatearSituacion } from '../utils/calculos';
|
|
|
|
|
|
|
|
const totalRecursos = 20;
|
|
|
|
const recursosActivos = 15;
|
|
|
|
const totalRecursos: number = 20;
|
|
|
|
const recursosActivos: number = 15;
|
|
|
|
|
|
|
|
console.log(
|
|
|
|
`Porcentaje de recursos en ACTIVIDAD: ` +
|
|
|
|
`${calcularPorcentajeActividad(totalRecursos, recursosActivos)}%`
|
|
|
|
`Porcentaje de recursos en ACTIVIDAD: ${calcularPorcentajeActividad(totalRecursos, recursosActivos)}%`
|
|
|
|
);
|
|
|
|
|
|
|
|
console.log(`Situación formateada: ${formatearSituacion('BAJA_MEDICA')}`);
|
|
|
|
```
|
|
|
|
|
|
|
|
**Salida esperada:**
|
|
|
|
|
|
|
|
```
|
|
|
|
Porcentaje de recursos en ACTIVIDAD: 75.0%
|
|
|
|
Situación formateada: Baja medica
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 3. Importación de clases
|
|
|
|
|
|
|
|
Aquí adaptamos el ejemplo a tu modelo real: `Recurso` es abstracto, así que podemos crear una clase `RecursoHumanoJS` que emula la estructura de tu API en front.
|
|
|
|
Archivo `models/RecursoHumano.ts`:
|
|
|
|
|
|
|
|
Archivo `models/RecursoHumano.js`:
|
|
|
|
|
|
|
|
```js
|
|
|
|
// models/RecursoHumano.js
|
|
|
|
```ts
|
|
|
|
// models/RecursoHumano.ts
|
|
|
|
export class RecursoHumano {
|
|
|
|
constructor(id, nombreRecurso, unidad, tipoSituacion) {
|
|
|
|
this.id = id;
|
|
|
|
this.nombreRecurso = nombreRecurso;
|
|
|
|
this.unidad = unidad;
|
|
|
|
this.tipoRecurso = 'Humano';
|
|
|
|
this.tipoSituacion = tipoSituacion;
|
|
|
|
}
|
|
|
|
constructor(
|
|
|
|
public id: number,
|
|
|
|
public nombreRecurso: string,
|
|
|
|
public unidad: string,
|
|
|
|
public tipoSituacion: string
|
|
|
|
) {}
|
|
|
|
|
|
|
|
mostrarFicha() {
|
|
|
|
readonly tipoRecurso: string = 'Humano';
|
|
|
|
|
|
|
|
mostrarFicha(): void {
|
|
|
|
console.log(
|
|
|
|
`Recurso Humano #${this.id}: ${this.nombreRecurso} ` +
|
|
|
|
`- Unidad: ${this.unidad} (${this.tipoSituacion})`
|
|
|
|
`Recurso Humano #${this.id}: ${this.nombreRecurso} - Unidad: ${this.unidad} (${this.tipoSituacion})`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Archivo `gestion/personal.js`:
|
|
|
|
Archivo `gestion/personal.ts`:
|
|
|
|
|
|
|
|
```js
|
|
|
|
// gestion/personal.js
|
|
|
|
import { RecursoHumano } from '../models/RecursoHumano.js';
|
|
|
|
```ts
|
|
|
|
// gestion/personal.ts
|
|
|
|
import { RecursoHumano } from '../models/RecursoHumano';
|
|
|
|
|
|
|
|
const tecnico = new RecursoHumano(1, 'Laura Gómez', 'AGRUSAN', 'ACTIVIDAD');
|
|
|
|
const medico = new RecursoHumano(2, 'Javier Ruiz', 'NAS 11', 'COMISION_SERVICIO');
|
| ... | ... | @@ -245,34 +234,28 @@ tecnico.mostrarFicha(); |
|
|
|
medico.mostrarFicha();
|
|
|
|
```
|
|
|
|
|
|
|
|
**Salida esperada:**
|
|
|
|
|
|
|
|
```
|
|
|
|
Recurso Humano #1: Laura Gómez - Unidad: AGRUSAN (ACTIVIDAD)
|
|
|
|
Recurso Humano #2: Javier Ruiz - Unidad: NAS 11 (COMISION_SERVICIO)
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 4. Buenas prácticas
|
|
|
|
## 4. Buenas prácticas en TypeScript
|
|
|
|
|
|
|
|
- Usar rutas relativas (`./` o `../`) para importar módulos locales.
|
|
|
|
- Incluir siempre la extensión `.js` en los módulos.
|
|
|
|
- Organizar el proyecto en carpetas como `/data`, `/utils` y `/models`.
|
|
|
|
- Usar `export default` cuando el módulo exporta un único elemento.
|
|
|
|
* Evitar `any`; usar `interface` o `type`.
|
|
|
|
* No es necesario indicar la extensión `.ts` en los imports.
|
|
|
|
* Usar **barrel files** (`index.ts`) para agrupar exports.
|
|
|
|
* Separar modelos (`/models`), utilidades (`/utils`) y lógica (`/gestion`).
|
|
|
|
|
|
|
|
Ejemplo adaptado al dominio:
|
|
|
|
Ejemplo con exportación por defecto:
|
|
|
|
|
|
|
|
```js
|
|
|
|
// utils/logger.js
|
|
|
|
export default function log(mensaje) {
|
|
|
|
```ts
|
|
|
|
// utils/logger.ts
|
|
|
|
export default function log(mensaje: string): void {
|
|
|
|
console.log(`[Sistema Recursos]: ${mensaje}`);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
```js
|
|
|
|
// main.js
|
|
|
|
import log from './utils/logger.js';
|
|
|
|
```ts
|
|
|
|
// main.ts
|
|
|
|
import log from './utils/logger';
|
|
|
|
|
|
|
|
log('Sistema de activaciones inicializado.');
|
|
|
|
```
|
|
|
|
|