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;voidmarca 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.readonlyimpide 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<T> {
data: T;
status: number;
}
const response: ApiResponse<Book> = { data: book, status: 200 };
<T>es un parámetro de tipo que se fija en cada uso:ApiResponse<Book>tienedatade tipoBook.- Sirve para un mismo envoltorio con distintos contenidos;
Array<string>es lo mismo questring[].
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.
exportpublica yimportconsume; la extensión.jsdel import corresponde al archivo compilado dedist/.
8. Tipos y datos de una API
interface BookResponse {
id: number;
title: string;
authorName: string;
}
async function getBook(id: number): Promise<BookResponse> {
const response = await fetch(`/api/books/${id}`);
return response.json();
}
fetchyasync/awaitse 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.