Tema
Instalación y tsconfig
Para usar TypeScript necesitas el compilador y un archivo de configuración que le diga cómo revisar y compilar tu código. En esta lección instalarás TypeScript en un proyecto, entenderás las opciones más importantes del tsconfig.json y conocerás las formas modernas de ejecutar TS: tsx, Vite y el Playground.
Concepto
El compilador de TypeScript se llama tsc (TypeScript Compiler). Hace dos trabajos:
- Revisar tipos (type checking): encuentra errores.
- Emitir JavaScript: genera los archivos
.jssin tipos.
El archivo tsconfig.json es como el panel de control del compilador: qué archivos revisar, qué tan estricto ser, a qué versión de JavaScript compilar y dónde dejar el resultado.
Instalación paso a paso
Se recomienda instalar TypeScript por proyecto (como dependencia de desarrollo), no de forma global. Así cada proyecto fija su versión.
bash
# 1. Crea la carpeta y el package.json
mkdir mi-proyecto-ts
cd mi-proyecto-ts
npm init -y
# 2. Instala TypeScript como dependencia de desarrollo
npm i -D typescript
# 3. Verifica la versión
npx tsc --version
# 4. Genera un tsconfig.json con valores recomendados
npx tsc --initnpx ejecuta el tsc instalado en node_modules. Si necesitas repasar npm, revisa npm y package.json.
Primer archivo y compilación
Crea src/index.ts:
ts
// src/index.ts
interface Producto {
nombre: string;
precio: number;
}
const productos: Producto[] = [
{ nombre: 'Mouse', precio: 349 },
{ nombre: 'Teclado', precio: 1299 }
];
// Sumamos los precios: TS sabe que p.precio es number
const total = productos.reduce((suma, p) => suma + p.precio, 0);
console.log(`Total: $${total}`);Compila y ejecuta:
bash
npx tsc # revisa todo el proyecto y genera los .js en outDir
node dist/index.js # ejecuta el JavaScript generadoComandos útiles de tsc:
bash
npx tsc --watch # recompila cada vez que guardas
npx tsc --noEmit # solo revisa tipos, no genera archivos (muy usado en CI)Agrégalos a tu package.json:
json
{
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"typecheck": "tsc --noEmit"
}
}El tsconfig.json explicado
npx tsc --init genera un archivo enorme lleno de comentarios. Este es un tsconfig.json limpio y moderno con las opciones que de verdad importan:
json
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": ["ES2022"],
"rootDir": "src",
"outDir": "dist",
"strict": true,
"noUncheckedIndexedAccess": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src"]
}Veamos qué hace cada una.
target
La versión de JavaScript que se genera. Con ES2022, TS deja tal cual async/await, clases, ?. y ??. Con un target viejo como ES5, TS reescribe todo eso en código antiguo (más largo). Hoy, navegadores modernos y Node 18+ soportan ES2022 sin problema.
module
Qué sistema de módulos usa el JavaScript generado:
NodeNext: para proyectos de Node; respeta"type": "module"delpackage.json.ESNext: deja losimport/exportintactos; ideal cuando un bundler (Vite) procesa el código.CommonJS: generarequireymodule.exports(proyectos Node antiguos).
moduleResolution
Cómo TS encuentra los archivos que importas.
NodeNext: igual que Node moderno. Exige extensiones en imports relativos:import { x } from './utils.js'(sí,.jsaunque el archivo sea.ts).Bundler: para proyectos con Vite, webpack o similares. Permite imports sin extensión.
Regla rápida
Node puro → module y moduleResolution en NodeNext. Frontend con Vite → module: "ESNext" y moduleResolution: "Bundler".
lib
Qué APIs "integradas" conoce TS. ES2022 incluye Array.prototype.at, Object.hasOwn, etc. Si trabajas en el navegador agrega "DOM" y "DOM.Iterable" para tener document, HTMLElement, fetch y compañía.
json
"lib": ["ES2022", "DOM", "DOM.Iterable"]rootDir y outDir
rootDir: dónde está tu código fuente (src).outDir: dónde se guarda el JavaScript compilado (dist).
Así src/utils/fecha.ts termina en dist/utils/fecha.js, manteniendo la estructura. Agrega dist a tu .gitignore.
strict
La opción más importante. Activa un paquete de revisiones estrictas, entre ellas:
strictNullChecks:nullyundefinedno se pueden usar como si fueran otro tipo.noImplicitAny: si TS no puede inferir un tipo, te obliga a escribirlo en vez de usaranyen silencio.strictFunctionTypes,strictPropertyInitializationy otras.
ts
// Con strict: true
function saludar(nombre) {
// ❌ Parameter 'nombre' implicitly has an 'any' type.
return 'Hola ' + nombre;
}
const input = document.querySelector('input');
input.value = 'hola';
// ❌ 'input' is possibly 'null'.Buena práctica
Activa siempre "strict": true en proyectos nuevos. Sin él, TypeScript deja pasar muchos de los errores que justamente quieres atrapar.
noUncheckedIndexedAccess
No viene dentro de strict, pero es muy recomendable. Hace que acceder a un array o diccionario por índice devuelva T | undefined, porque el elemento podría no existir:
ts
const colores = ['rojo', 'verde'];
const tercero = colores[2]; // tipo: string | undefined
tercero.toUpperCase();
// ❌ 'tercero' is possibly 'undefined'.
// Debes comprobarlo antes
if (tercero) {
console.log(tercero.toUpperCase()); // ✅
}Otras opciones útiles
esModuleInterop: permiteimport express from 'express'con librerías CommonJS.skipLibCheck: no revisa los.d.tsdenode_modules(compila más rápido y evita errores ajenos).forceConsistentCasingInFileNames: evita bugs entre Windows (no distingue mayúsculas) y Linux (sí las distingue).include: qué carpetas revisa TS.
Ejecutar TS directamente con tsx
Compilar y luego ejecutar es lento para desarrollar. tsx ejecuta archivos .ts al vuelo:
bash
npm i -D tsx
npx tsx src/index.ts # ejecuta una vez
npx tsx watch src/index.ts # reinicia al guardarjson
{
"scripts": {
"dev": "tsx watch src/index.ts",
"typecheck": "tsc --noEmit",
"build": "tsc"
}
}Error común
tsx (y Vite, esbuild o Node con su modo de quitar tipos) no revisa tipos: solo los borra y ejecuta. Tu código puede correr aunque tenga errores de tipo. Por eso siempre conviene tener el script typecheck con tsc --noEmit y correrlo antes de subir cambios.
Proyecto de frontend con Vite + TypeScript
Para frontend lo más práctico es Vite, que ya trae TypeScript configurado:
bash
npm create vite@latest mi-app -- --template vanilla-ts
cd mi-app
npm install
npm run devPlantillas útiles: vanilla-ts, react-ts, vue-ts, svelte-ts.
Vite genera un tsconfig.json pensado para el navegador (resumido):
json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"strict": true,
"noEmit": true,
"skipLibCheck": true
},
"include": ["src"]
}Fíjate en "noEmit": true: en Vite, tsc solo revisa tipos y es Vite quien genera el JavaScript final. Por eso el script de build suele ser tsc && vite build (primero revisa, luego empaqueta).
TypeScript Playground
Para experimentar sin instalar nada, usa el TypeScript Playground: https://www.typescriptlang.org/play. Escribes TS a la izquierda y ves el JS generado a la derecha, con los errores marcados. Es perfecto para probar los ejemplos de este curso.
Ejercicios
- Crea un proyecto con
npm init -y, instala TypeScript y genera untsconfig.json. ConfigurarootDir: "src"youtDir: "dist". - Agrega a
package.jsontres scripts:dev(con tsx watch),typecheckybuild. - ¿Qué opciones de
lib,moduleymoduleResolutionusarías para un proyecto de navegador con Vite? - Con
noUncheckedIndexedAccessactivo, corrige este código:
ts
const precios = [100, 250, 80];
const primero = precios[0];
console.log(primero.toFixed(2));Ver solución
- y 2.
bash
mkdir ejercicio-ts && cd ejercicio-ts
npm init -y
npm i -D typescript tsx
npx tsc --initjson
{
"scripts": {
"dev": "tsx watch src/index.ts",
"typecheck": "tsc --noEmit",
"build": "tsc"
}
}En tsconfig.json: "rootDir": "src" y "outDir": "dist".
lib: ["ES2022", "DOM", "DOM.Iterable"],module: "ESNext",moduleResolution: "Bundler".
ts
const precios = [100, 250, 80];
const primero = precios[0]; // number | undefined
if (primero !== undefined) {
console.log(primero.toFixed(2));
}
// O con un valor por defecto
console.log((precios[0] ?? 0).toFixed(2));Resumen
- Instala TypeScript por proyecto:
npm i -D typescript; genera la config connpx tsc --init. tscrevisa tipos y emite JS;tsc --noEmitsolo revisa.strict: truesiempre;noUncheckedIndexedAccesses un gran extra.targetdefine la versión de JS generada;moduleymoduleResolutiondependen de si usas Node (NodeNext) o un bundler (ESNext+Bundler).- Agrega
DOMalibpara código de navegador. tsxy Vite ejecutan TS rápido pero no revisan tipos: complementa contsc --noEmit.- El Playground es ideal para experimentar.
Siguiente: Tipos básicos