✨ Introducción al curso

Bienvenido a este curso de TypeScript. Aquí aprenderás desde los fundamentos hasta técnicas modernas para crear aplicaciones web robustas y escalables.
No necesitas conocimientos previos de TypeScript, solo familiaridad con JavaScript y un editor de código.

¿Qué encontrarás en este curso?

  • Explicaciones claras con ejemplos prácticos modernos
  • Diferencias clave entre TypeScript y JavaScript
  • Ejercicios prácticos con soluciones explicadas
  • Proyectos finales para consolidar tus conocimientos
  • Buenas prácticas y patrones de diseño con tipos
  • Glosario y recursos recomendados

📝 Glosario de términos clave

Término Definición breve
Tipo Define la estructura de datos que una variable puede contener
Interfaz Contrato que define la forma de un objeto
Genérico Tipo que puede trabajar con múltiples tipos de datos
Decorador Patrón para añadir funcionalidad a clases/métodos
Union Type Tipo que puede ser uno de varios tipos
Type Inference Capacidad de TS para inferir tipos automáticamente
Type Assertion Indicación explícita del tipo de un valor
Módulo Sistema para organizar código en archivos separados
Compilador Herramienta que transforma TS a JS
Declaration Files Archivos .d.ts que describen tipos de librerías JS

🦾 Buenas prácticas y patrones modernos

  • Usa tipos explícitos para APIs públicas e implícitos donde sea obvio
  • Prefiere interfaces sobre types para objetos y clases
  • Usa genéricos para crear componentes reutilizables
  • Aprovecha los tipos literales para mayor seguridad
  • Organiza tu código en módulos lógicos
  • Usa strict mode en tsconfig.json
  • Escribe archivos de declaración para extender librerías JS
  • Utiliza utility types (Partial, Pick, Omit) cuando sea apropiado
  • Documenta tipos complejos con comentarios JSDoc

♿ Accesibilidad y seguridad con TypeScript

  • Usa tipos estrictos para validar datos de entrada del usuario
  • Define tipos precisos para propiedades accesibles (ARIA)
  • Crea tipos discriminados para estados de UI accesibles
  • Usa never para casos inalcanzables en switches exhaustivos
  • Aprovecha las aserciones de tipo para DOM seguro
  • Implementa guards de tipo para validación en runtime

🏋️‍♂️ Ejercicios prácticos

Cada sección incluye ejercicios para practicar. ¡Intenta resolverlos antes de ver la solución!


1️⃣ Fundamentos de TypeScript

Descripción

Aprenderás qué es TypeScript, cómo configurarlo y las diferencias clave con JavaScript.


📖 ¿Qué es TypeScript?

TypeScript es un superset tipado de JavaScript que compila a JavaScript puro. Desarrollado por Microsoft, añade tipos estáticos y herramientas avanzadas a JS.

Ventajas

  • Detección temprana de errores
  • Mejor autocompletado y documentación en el editor
  • Código más mantenible y escalable
  • Compatibilidad con todo el ecosistema JavaScript
  • Funcionalidades futuras de JS hoy (decoradores, etc.)

📖 Configuración inicial

  1. Instalar TypeScript globalmente:
npm install -g typescript
  1. Inicializar proyecto:
tsc --init
  1. Configurar tsconfig.json:
{
  "compilerOptions": {
    "target": "ES6",
    "module": "ES6",
    "strict": true,
    "outDir": "./dist"
  },
  "include": ["src/**/*"]
}

📖 Tipos básicos

let nombre: string = "Ana";
let edad: number = 25;
let activo: boolean = true;
let lista: number[] = [1, 2, 3];
let tupla: [string, number] = ["Ana", 25]; // Arreglo con tipos fijos
enum Color {Rojo, Verde, Azul}; // Enumeraciones
let cualquiera: any = "puede ser cualquier cosa"; // Evitar cuando sea posible
let vacio: void = undefined; // Para funciones sin retorno
let nulo: null = null;
let indefinido: undefined = undefined;
let nunca: never; // Para funciones que nunca retornan

📖 Interfaces

Definen la forma de un objeto:

interface Usuario {
  nombre: string;
  edad: number;
  direccion?: string; // Opcional
}

let usuario: Usuario = {
  nombre: "Ana",
  edad: 25
};

📖 Funciones tipadas

function saludar(nombre: string): string {
  return `Hola, ${nombre}`;
}

// Función flecha con tipo
const sumar = (a: number, b: number): number => a + b;

// Parámetros opcionales
function nombreCompleto(nombre: string, apellido?: string): string {
  return apellido ? `${nombre} ${apellido}` : nombre;
}

// Valores por defecto
function multiplicar(a: number, b: number = 1): number {
  return a * b;
}

📖 Clases

class Persona {
  // Propiedades
  nombre: string;
  private edad: number; // Privado
  
  constructor(nombre: string, edad: number) {
    this.nombre = nombre;
    this.edad = edad;
  }
  
  // Método
  saludar(): string {
    return `Hola, soy ${this.nombre}`;
  }
}

let ana = new Persona("Ana", 25);
console.log(ana.saludar());

2️⃣ Tipos avanzados

Union Types

let id: string | number;
id = "ABC123"; // OK
id = 123; // OK
id = true; // Error

Type Aliases

type ID = string | number;
let userId: ID = "ABC123";

Literal Types

type Direccion = "norte" | "sur" | "este" | "oeste";
let direccion: Direccion = "norte";

📖 Genéricos

Permiten crear componentes reutilizables:

function identidad<T>(arg: T): T {
  return arg;
}

let salida = identidad<string>("hola");
let salida2 = identidad<number>(42);

// Con interfaces
interface Caja<T> {
  contenido: T;
}

let cajaString: Caja<string> = { contenido: "hola" };
let cajaNumero: Caja<number> = { contenido: 42 };

📖 Utility Types

TypeScript provee tipos útiles:

interface Usuario {
  nombre: string;
  edad: number;
  email: string;
}

// Partial: todas las propiedades opcionales
type UsuarioParcial = Partial<Usuario>;

// Pick: selecciona propiedades específicas
type UsuarioBasico = Pick<Usuario, "nombre" | "email">;

// Omit: excluye propiedades
type UsuarioSinEmail = Omit<Usuario, "email">;

// Record: crea un tipo con propiedades de un tipo específico
type UsuariosPorId = Record<string, Usuario>;

3️⃣ Módulos y Namespaces

Módulos ES6

// math.ts
export function sumar(a: number, b: number): number {
  return a + b;
}

// app.ts
import { sumar } from './math';
console.log(sumar(2, 3));

Namespaces

namespace Validacion {
  export function esEmail(valor: string): boolean {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(valor);
  }
}

let email = "test@example.com";
console.log(Validacion.esEmail(email));

4️⃣ Decoradores

(Requieren activar experimentalDecorators en tsconfig.json)

function log(target: any, key: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;
  
  descriptor.value = function(...args: any[]) {
    console.log(`Llamando a ${key} con`, args);
    const resultado = original.apply(this, args);
    console.log(`Resultado:`, resultado);
    return resultado;
  };
  
  return descriptor;
}

class Calculadora {
  @log
  sumar(a: number, b: number): number {
    return a + b;
  }
}

5️⃣ TypeScript con DOM

// Type assertions para elementos del DOM
const boton = document.getElementById("miBoton") as HTMLButtonElement;
const input = document.querySelector("input[type='text']") as HTMLInputElement;

// Manejador de eventos tipado
boton.addEventListener("click", (event: MouseEvent) => {
  console.log(`Hola, ${input.value}`);
  input.value = ""; // Limpiar input
});

// Creación dinámica de elementos
const div = document.createElement("div");
div.textContent = "Nuevo elemento";
document.body.appendChild(div);

6️⃣ TypeScript con APIs modernas

Fetch API con tipos

interface Post {
  userId: number;
  id: number;
  title: string;
  body: string;
}

async function obtenerPosts(): Promise<Post[]> {
  const respuesta = await fetch("https://jsonplaceholder.typicode.com/posts");
  return await respuesta.json();
}

obtenerPosts().then(posts => {
  posts.forEach(post => console.log(post.title));
});

7️⃣ Proyectos reales con TypeScript

Configuración para React

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES6",
    "module": "ESNext",
    "jsx": "react-jsx",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

Componente React tipado

interface Props {
  nombre: string;
  edad?: number;
}

const Saludo: React.FC<Props> = ({ nombre, edad = 25 }) => {
  return (
    <div>
      Hola, {nombre}. Tienes {edad} años.
    </div>
  );
};

Uso de Hooks con TypeScript

import React, { useState } from "react";
const Contador: React.FC = () => {
  const [contador, setContador] = useState(0);
  return (
    <div>
      <p>Contador: {contador}</p>
      <button onClick={() => setContador(contador + 1)}>Incrementar</button>
    </div>
  );
};

Uso de TypeScript con React Router

import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "./Home";
import About from "./About";
import Contact from "./Contact";
const App: React.FC = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
      </Routes>
    </BrowserRouter>
  );
};