====== 06 - TypeScript ====== **TypeScript** es un superconjunto tipado de **JavaScript** (tema 04): añade **tipos estáticos** que el compilador comprueba y que **no existen en la ejecución**. Se compila con **tsc**, y el JavaScript resultante es lo que ejecutan el navegador y **Node**. La instalación del proyecto con npm se explica en el tema 05. ===== 1. Compilación ===== npm install --save-dev typescript # dependencia de desarrollo (tema 05) npx tsc src/main.ts # compila un fichero suelto npx tsc # compila según tsconfig.json npx tsc --watch # recompila al guardar node dist/main.js # ejecuta el resultado compilado El ''tsconfig.json'' configura la compilación; ''npx tsc --init'' genera uno de partida: { "compilerOptions": { "target": "es2022", "module": "es2022", "outDir": "dist", "rootDir": "src", "strict": true } } ^ Opción ^ Función ^ | ''target'' | versión de JavaScript que genera el compilador | | ''module'' | sistema de módulos del resultado (''import''/''export'') | | ''outDir'' / ''rootDir'' | carpeta de salida (''dist'') y de origen (''src'') | | ''strict'' | exige disciplina de tipos; configuración recomendada | ===== 2. Anotaciones e inferencia ===== const id: number = 42; const title: string = "Código limpio"; const available = true; // boolean: lo deduce el compilador const tags: string[] = ["programming", "craft"]; const pair: [string, number] = ["total", 3]; // tupla: tipos por posición function discount(price: number, percent: number): number { return price * (1 - percent / 100); } function announce(message: string): void { // no devuelve nada console.log(message); } * La anotación se escribe tras el nombre: ''id: number''; ''void'' marca funciones sin retorno. * Cuando el valor es evidente, el compilador deduce el tipo sin anotarlo (''available''). * No hay conversión implícita: ''discount("100", 20)'' no compila. ===== 3. Interfaces ===== Una interfaz describe la **forma** de los datos, no su comportamiento: interface Book { id: number; title: string; available: boolean; authorId?: number; // opcional: puede faltar readonly createdAt: Date; // no modificable tras crearlo } const book: Book = { id: 1, title: "Código limpio", available: true, createdAt: new Date(), }; * ''?'' marca la propiedad que puede faltar; el compilador obliga a contemplar su ausencia al usarla. * ''readonly'' impide modificar la propiedad desde el exterior tras crear el objeto. ===== 4. Uniones, literales y narrowing ===== Los **tipos literales** restringen un valor a opciones concretas: type Genre = "novela" | "ensayo" | "teatro"; type OrderStatus = "PENDING" | "CONFIRMED" | "CANCELLED"; function canCancel(status: OrderStatus): boolean { return status === "PENDING"; } canCancel("SENT"); // error de compilación: el literal no está en la unión Una unión también puede mezclar tipos; en cada rama el compilador **acota** el tipo disponible: function describe(value: string | number): string { if (typeof value === "string") return value; return `id ${value}`; // aquí, value es number } ===== 5. any y unknown ===== let data: any = JSON.parse(text); // evítalo: desactiva la comprobación let payload: unknown = JSON.parse(text); // admite cualquier valor, // pero exige comprobar el tipo antes de usarlo if (typeof payload === "string") { console.log(payload.toUpperCase()); // ok: ya es string } ''any'' contagia la ausencia de tipos a todo lo que toca; ''unknown'' obliga a comprobar el tipo antes de operar. Se usa ''unknown'' cuando no se conoce el contenido y tipos concretos en cuanto se pueda. ===== 6. Genéricos ===== interface ApiResponse { data: T; status: number; } const response: ApiResponse = { data: book, status: 200 }; * '''' es un parámetro de tipo que se fija en cada uso: ''ApiResponse'' tiene ''data'' de tipo ''Book''. * Sirve para un mismo envoltorio con distintos contenidos; ''Array'' es lo mismo que ''string[]''. ===== 7. Clases y módulos ===== // src/price-calculator.ts export class PriceCalculator { discount(price: number, percent: number): number { return price * (1 - percent / 100); } } // src/main.ts import { PriceCalculator } from "./price-calculator.js"; const calculator = new PriceCalculator(); console.log(calculator.discount(100, 20)); // 80 * La POO es la ya estudiada en Programación; TypeScript añade los tipos a campos, parámetros y retorno. * ''export'' publica y ''import'' consume; la extensión ''.js'' del import corresponde al **archivo compilado** de ''dist/''. ===== 8. Tipos y datos de una API ===== interface BookResponse { id: number; title: string; authorName: string; } async function getBook(id: number): Promise { const response = await fetch(`/api/books/${id}`); return response.json(); } * ''fetch'' y ''async''/''await'' se explican en el tema 07; el tipo describe el JSON que entregará la API. * Si la API cambia su JSON, el compilador avisa de todos los puntos del cliente que necesitan adaptarse. Los tipos no existen en la ejecución: no viajan en el JSON ni validan lo que llega. Su valor está en detectar errores antes de ejecutar y en documentar la forma de los datos que viajan entre cliente y API.