TypeScript es un superconjunto tipado de JavaScript desarrollado y mantenido por Microsoft. Compila a JavaScript estándar y puede ejecutarse en cualquier entorno donde corra JS.
Ventajas clave en 2026
Detección de errores en tiempo de compilación — los bugs aparecen antes de llegar a producción
Autocompletado e IntelliSense — productividad muy superior en cualquier editor
Refactoring seguro — renombrar o mover código sin miedo
Documentación viva — los tipos sirven como documentación que siempre está actualizada
Ecosistema maduro — prácticamente todas las librerías populares tienen soporte de tipos
JavaScript vs TypeScript
2. Instalación y configuración
Requisitos previos
Node.js 20+ (LTS recomendado)
npm, pnpm o bun
Instalación global
Inicializar un proyecto
tsconfig.json básico (2026)
Scripts en package.json
Tip 2026: Usa tsx en lugar de ts-node para desarrollo — es mucho más rápido al estar basado en esbuild.
3. Tipos básicos
Primitivos
Arrays y Tuplas
any, unknown, never y void
Enums
Alternativa moderna a enums: Muchos equipos prefieren usar as const con objetos:
4. Funciones tipadas
Tipos de parámetros y retorno
Tipos de función
Funciones de orden superior
5. Interfaces y Types
Interface
Type Alias
Interface vs Type — ¿Cuándo usar cada uno?
Característica
Interface
Type
Declaration merging
✅
❌
Extends / implements
✅
❌ (usa &)
Tipos primitivos
❌
✅
Uniones / intersecciones
❌
✅
Tipos mapeados
❌
✅
Mejor para objetos/clases
✅
✅
Regla práctica 2026: Usa interface para contratos de objetos y clases. Usa type para uniones, alias de tipos primitivos y tipos calculados.
6. Clases y Programación Orientada a Objetos
Clases básicas
Herencia e interfaces
Clases abstractas
Clases estáticas y Singleton
7. Genéricos
Los genéricos son una de las características más poderosas de TypeScript. Permiten crear componentes reutilizables que funcionan con cualquier tipo.
Los decoradores son una característica experimental (ahora estable en TS 5.0+) que permite añadir metadatos y modificar el comportamiento de clases y sus miembros.
11. TypeScript con React
Configuración
Componentes tipados
Hooks tipados
Context API tipado
12. TypeScript con Node.js y Express
Configuración del proyecto
Servidor Express tipado
13. Utilidades del sistema de tipos
TypeScript incluye tipos de utilidad predefinidos que simplifican transformaciones comunes.
TypeScript ha pasado de ser una opción a convertirse en el estándar de la industria en 2026. Su sistema de tipos progresivo te permite adoptarlo gradualmente en proyectos existentes y escalarlo a medida que tu equipo y proyecto crecen.
La clave para dominar TypeScript es:
Activar strict: true desde el inicio
Evitar any — usa unknown y type guards
Deja que TypeScript infiera cuando pueda; solo anota cuando sea necesario
Una sola fuente de verdad — usa Zod o similar para que tipos y validaciones estén sincronizados
Leer los errores del compilador — son tus mejores aliados, no tus enemigos
¡Ahora estás listo para escribir TypeScript de nivel profesional!
Última actualización: 2026 · TypeScript 5.6+
javascript
// JavaScript — sin protecciónfunction suma(a, b) { return a + b;}suma("10", 5); // "105" — bug silencioso
typescript
// TypeScript — error detectado al compilarfunction suma(a: number, b: number): number { return a + b;}suma("10", 5); // ❌ Error: Argument of type 'string' is not assignable to parameter of type 'number'
bash
npm install -g typescripttsc --version # Verifica la versión instalada
// any — desactiva el sistema de tipos (evitar siempre que sea posible)let cualquierCosa: any = "texto";cualquierCosa = 42;cualquierCosa.metodoInventado(); // No da error, pero puede fallar en runtime// unknown — versión segura de anylet entrada: unknown = obtenerDatoExterno();// entrada.toLowerCase(); ❌ Error — debes verificar el tipo primeroif (typeof entrada === "string") { console.log(entrada.toLowerCase()); // ✅ Ahora es seguro}// never — representa valores que nunca ocurrenfunction lanzarError(mensaje: string): never { throw new Error(mensaje);}function verificarExhaustividad(valor: never): never { throw new Error(`Caso no manejado: ${valor}`);}// void — funciones que no retornan valor significativofunction imprimirSaludo(): void { console.log("¡Hola!");}
typescript
// Enum numéricoenum Direccion { Norte, // 0 Sur, // 1 Este, // 2 Oeste, // 3}// Enum de cadena (recomendado en 2026)enum Estado { Activo = "ACTIVO", Inactivo = "INACTIVO", Pendiente = "PENDIENTE",}const estadoUsuario: Estado = Estado.Activo;console.log(estadoUsuario); // "ACTIVO"// Const enums — se eliminan en compilación (mejor rendimiento)const enum TipoHttp { Get = "GET", Post = "POST", Put = "PUT", Delete = "DELETE",}
typescript
const ESTADO = { Activo: "ACTIVO", Inactivo: "INACTIVO", Pendiente: "PENDIENTE",} as const;type Estado = typeof ESTADO[keyof typeof ESTADO];// Estado = "ACTIVO" | "INACTIVO" | "PENDIENTE"
typescript
// Parámetros tipados y tipo de retorno explícitofunction saludar(nombre: string, titulo?: string): string { const t = titulo ? `${titulo} ` : ""; return `Hola, ${t}${nombre}!`;}saludar("Carlos"); // "Hola, Carlos!"saludar("Ana", "Dra."); // "Hola, Dra. Ana!"// Parámetros con valor por defectofunction crearUsuario( nombre: string, rol: string = "visitante", activo: boolean = true): { nombre: string; rol: string; activo: boolean } { return { nombre, rol, activo };}// Parámetros restfunction sumarTodos(...numeros: number[]): number { return numeros.reduce((acc, n) => acc + n, 0);}sumarTodos(1, 2, 3, 4, 5); // 15
typescript
// Definir el tipo de una funcióntype Operacion = (a: number, b: number) => number;const sumar: Operacion = (a, b) => a + b;const multiplicar: Operacion = (a, b) => a * b;// Sobrecarga de funcionesfunction procesar(valor: string): string;function procesar(valor: number): number;function procesar(valor: string | number): string | number { if (typeof valor === "string") { return valor.toUpperCase(); } return valor * 2;}const r1 = procesar("hola"); // tipo: stringconst r2 = procesar(5); // tipo: number
// matematicas.tsexport function sumar(a: number, b: number): number { return a + b;}export const PI = 3.14159265358979;export interface Punto { x: number; y: number;}export default class Calculadora { private historial: number[] = []; operar(a: number, operacion: (x: number) => number): number { const resultado = operacion(a); this.historial.push(resultado); return resultado; }}
typescript
// app.tsimport Calculadora, { sumar, PI, type Punto } from "./matematicas.js";const calc = new Calculadora();console.log(sumar(2, 3));console.log(PI);// Re-exportarexport { sumar as suma } from "./matematicas.js";export * from "./matematicas.js";export * as Matematicas from "./matematicas.js";
typescript
// tsconfig: "experimentalDecorators": true (TS < 5.0)// En TS 5.0+ los decoradores siguen el estándar TC39// Decorador de clasefunction Registrable(clase: new (...args: any[]) => any) { console.log(`Clase registrada: ${clase.name}`); return clase;}// Decorador con parámetros (factory)function Componente(opciones: { selector: string; plantilla: string }) { return function(clase: new (...args: any[]) => any) { (clase as any).selector = opciones.selector; (clase as any).plantilla = opciones.plantilla; return clase; };}// Decorador de métodofunction Memoize( _target: any, _propertyKey: string, descriptor: PropertyDescriptor) { const metodoOriginal = descriptor.value; const cache = new Map<string, any>(); descriptor.value = function(...args: any[]) { const clave = JSON.stringify(args); if (cache.has(clave)) { console.log("Resultado desde caché"); return cache.get(clave); } const resultado = metodoOriginal.apply(this, args); cache.set(clave, resultado); return resultado; }; return descriptor;}// Decorador de propiedadfunction Validar(min: number, max: number) { return function(target: any, propertyKey: string) { let valor: number; Object.defineProperty(target, propertyKey, { get: () => valor, set: (nuevoValor: number) => { if (nuevoValor < min || nuevoValor > max) { throw new RangeError( `${propertyKey} debe estar entre ${min} y ${max}` ); } valor = nuevoValor; }, }); };}@Registrable@Componente({ selector: "app-usuario", plantilla: "<div>...</div>" })class ServicioUsuario { @Validar(0, 120) edad!: number; @Memoize calcularDescuento(precio: number): number { console.log("Calculando descuento..."); return precio * 0.9; }}
bash
# Crear proyecto con Vite (recomendado en 2026)npm create vite@latest mi-app -- --template react-tscd mi-appnpm install
// Predicados de tipo inferidos automáticamente (TS 5.5+)const usuarios = [ { id: 1, nombre: "Ana" }, null, { id: 2, nombre: "Luis" }, undefined,];// Antes necesitabas escribir el type guard manualmenteconst usuariosValidos = usuarios.filter(u => u !== null && u !== undefined);// En TS 5.5, TypeScript infiere el tipo correctamente: { id: number; nombre: string }[]
typescript
// Iteradores con tipo en TS 5.6+function* generarIds(): Generator<number, void, unknown> { let id = 1; while (true) { yield id++; }}async function* cargarPaginas<T>( url: string): AsyncGenerator<T[], void, unknown> { let pagina = 1; while (true) { const res = await fetch(`${url}?pagina=${pagina}`); const datos: T[] = await res.json(); if (datos.length === 0) return; yield datos; pagina++; }}
typescript
// Antes: el tipo se infería de forma ampliafunction crearTupla<T>(a: T, b: T): [T, T] { return [a, b];}const par = crearTupla("hola", "mundo"); // tipo: [string, string]// Con const — infiere tipos literalesfunction crearTuplaConst<const T>(a: T, b: T): [T, T] { return [a, b];}const parConst = crearTuplaConst("hola", "mundo"); // tipo: ["hola", "mundo"]
typescript
type ColoresPaleta = "rojo" | "verde" | "azul";type Paleta = Record<ColoresPaleta, string | [number, number, number]>;// satisfies — valida el tipo pero mantiene el tipo literal inferidoconst paleta = { rojo: [255, 0, 0], verde: "#00ff00", azul: [0, 0, 255],} satisfies Paleta;// Ahora paleta.rojo es [number, number, number] (no string | [...])paleta.rojo.map(c => c * 2); // ✅ TypeScript sabe que es un arraypaleta.verde.toUpperCase(); // ✅ TypeScript sabe que es string