From n00b to ZeroCool / Profesionalización
JavaScript vs TypeScript: la batalla por el tipado (sin humo)
Elige entre JavaScript y TypeScript con casos reales, ruta de migración incremental, errores comunes y checklist para tu frontend.
Lo que vale la pena leer aquí
Ayer, 6:47 pm. Ya estabas pensando en cerrar la laptop (de esas ya medio lentas, con el ventilador sonando como dron) cuando cae el mensaje en Slack/WhatsApp:
Ayer, 6:47 pm. Ya estabas pensando en cerrar la laptop (de esas ya medio lentas, con el ventilador sonando como dron) cuando cae el mensaje en Slack/WhatsApp:
“Oye, en production el botón de pagar ya no abre el modal… ¿tú moviste algo?”
Tú jurabas que no. Tu pull request fue “chiquito”: que una función aceptara un objeto “más completo”. En JavaScript, eso puede significar cualquier cosa. Y cuando truena, no hay abrazo. Hay presión, hay clientes, y hay un undefined viéndote directo a los ojos.
Ahí está la batalla del tipado: no es religión ni estatus. Es cuánto riesgo te avientas por moverte rápido… y cuánto te cuesta el rollback cuando el jefe pide el fix “en corto”.
Qué vas a sacar de aquí
- Qué problema resuelve de verdad TypeScript (y qué no).
- Cómo decidir JavaScript vs TypeScript según proyecto, equipo y deadline.
- Una ruta realista para migrar sin quemar el sprint:
allowJs,checkJs,tsconfig,strictpor etapas. - Ejemplos de bugs comunes que el tipado detecta antes del deploy.
- Errores típicos (los que hacen que la banda odie TS) y cómo evitarlos.
El tipado no te hace “más pro”: te baja la incertidumbre
JavaScript es flexible. Esa flexibilidad es poder… y también es caos cuando hay prisa.
TypeScript no reemplaza JavaScript: le pone un sistema de tipos estático que vive en tu editor y en CI. En runtime, el navegador o Node siguen corriendo JavaScript normal.
La decisión, en la vida real, suele verse así:
- Equipo chico + proyecto corto: JS te da velocidad.
- Producto que va a vivir meses/años + más gente metiendo mano: TS paga intereses.
- Freelance mal cotizado con soporte “cuando se pueda”: TS es como etiquetar cables antes de cerrar el rack. Te salva cuando regresas tres meses después y ya no te acuerdas ni qué era ese “hotfix rápido”.
Dos escenas que se repiten:
- Onboarding con docs “en Notion” que nadie actualiza. Con TS, el código explica más cosas y reduce el “oye, ¿esto qué recibe?” cada 10 minutos.
- Deploy tarde con CI lento y alguien compilando desde una laptop que ya pide retiro. TS puede sumar tiempo si lo metes a lo bruto, pero también te ahorra horas de debugging por bugs bien tontos.
Cómo decidir entre JavaScript y TypeScript sin pelearte con el equipo
1) Mide el riesgo: ¿qué tan caro es un bug?
Preguntas netas:
- ¿Este frontend mueve lana? (checkout, suscripción, pagos, logística)
- ¿Hay formularios con datos “raros” o incompletos?
- ¿Integras APIs que cambian seguido?
- ¿Hay rotación de devs o se sube banda nueva cada mes?
Si respondiste “sí” a 2 o más, TypeScript normalmente se paga rápido.
2) Revisa tu superficie de datos: ¿cuánta info viaja entre capas?
TS brilla cuando hay muchos objetos cruzando fronteras:
API -> normalizador -> state -> UIforms -> validation -> submitfeature flags -> permisos -> rutas
En una landing estática o un micrositio con 2 componentes, TS puede sentirse como cargar maleta para ir al Oxxo.
3) El “strictness” es una perilla, no un switch
El error clásico: creer que TS es “estricto o nada” o que la migración tiene que ser big-bang.
No. Bien usado, TypeScript es incremental. Y esa decisión (hacerlo por etapas) define si el workflow se vuelve más fluido o si todos lo van a esquivar con any.
Paso a paso: migrar de JavaScript a TypeScript sin romper todo
La meta no es “convertir todo a TS en una semana”. La meta es bajar bugs y subir claridad sin frenar el delivery.
Paso 0: Alinea expectativas (esto también es parte del setup)
Antes de tocar config, pónganse de acuerdo:
- ¿Qué queremos ganar? (menos bugs, mejor DX, refactors más seguros)
- ¿Qué no queremos? (bloquear merges por tipos imposibles)
- ¿Qué migramos primero? (lo más crítico, lo que más se rompe, o lo más aislado)
Si no se habla, TS se vuelve “otra regla” y lo van a duct-tapear con any.
Paso 1: Instala TypeScript y arranca con un tsconfig amable
npm i -D typescript
npx tsc --init
Un tsconfig.json inicial que no te incendie el backlog:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": false,
"noImplicitAny": false,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Decisión práctica: arranca con strict: false y sube el nivel por etapas. Avanzar 20% consistente vale más que “100%” con trauma y abandono.
Paso 2: Migración incremental con allowJs + checkJs
Si tu base está en JS, deja que convivan:
{
"compilerOptions": {
"allowJs": true,
"checkJs": false
},
"include": ["src"]
}
allowJs: truepermite que TS lea.js.checkJs: falseevita que te caiga una avalancha de warnings desde el día 1.
Cuando ya quieras valor sin convertir todo a .ts:
{
"compilerOptions": {
"checkJs": true
}
}
Y sí, // @ts-nocheck existe, pero úsalo como curita: solo donde de plano no puedes todavía, y con caducidad.
Paso 3: Empieza donde hay ROI: API, modelos y fronteras
El bug típico: “la API cambió un campo y nadie se enteró”.
Ejemplo bien real:
// JS
function formatUser(u) {
return u.profile.name.toUpperCase();
}
Si la API manda profile: null para usuarios incompletos, truena en runtime.
En TS, el código te obliga a decidir:
type User = {
id: string;
profile: null | {
name: string;
};
};
function formatUser(u: User) {
if (!u.profile) return "(sin perfil)";
return u.profile.name.toUpperCase();
}
Decisión práctica: tipa primero lo que cruza fronteras (API, storage, eventos, props). Ahí es donde más duele y más se rompe.
Paso 4: Migra por “islas”: .ts y .tsx
No conviertas todo el árbol de jalón. Haz islas:
src/api/(clientes, DTOs)src/utils/(helpers de fecha, money, parsing)- Componentes críticos (checkout, login, forms)
Regla que sirve: cada vez que toques un archivo por una feature, decide si conviene convertirlo en ese momento. Si sí, conviértelo. Si no, no te castigues.
Paso 5: Sube la perilla: strict por etapas
Cuando ya tengas base, el salto grande es strict: true. Pero se puede hacer gradual (por paquetes, carpetas o con reglas de lint).
Una ruta simple:
- Semana 1-2:
strict: false+ tipado en modelos/API. - Semana 3:
noImplicitAny: truepara forzar decisiones. - Semana 4+:
strict: trueen lo core (y tolerancia controlada en legacy).
Paso 6: Deja de pelearte con el editor: ESLint + typings bien puestos
Si usas React/Vue/Next, agrega los typings que toquen (depende del stack). La idea es que el editor no te “mienta” con autocompletados chuecos.
Y ojo: no normalices silenciar TS por sistema.
anyes un préstamo con intereses.unknownes un “alto” razonable: primero validas, luego usas.
Ejemplo:
function parsePrice(value: unknown): number {
if (typeof value === "number") return value;
if (typeof value === "string") return Number(value.replace(/[^0-9.]/g, ""));
return 0;
}
Esto pasa diario con forms o APIs que regresan cosas raras. TS te empuja a tratarlo como es, no como quisieras que fuera.

Ideas de screenshots (para que se entienda sin leer tanto)
- VS Code mostrando autocompletado y un error de tipo en una prop (
Property 'x' does not exist on type...). - Diff de un PR cambiando
.js -> .tsy agregando tipos a la respuesta del API. - Error típico en build (
Object is possibly 'null') y cómo lo resuelves con un guard.
Errores comunes (para no terminar odiando TypeScript)
1) “Metimos TS y ahora todo es any”
Síntoma: el repo “ya es TS”, pero nadie confía en los tipos.
Cómo salir:
- Bloquea
anyen código nuevo con ESLint o una convención clara. - Permite
anysolo con comentario justificado y ticket. - Prefiere
unknown+ validación.
2) Prender strict desde el día 1 en un legacy grande
Síntoma: 1,800 errores, el equipo se paraliza, se abandona la iniciativa.
Cómo salir: gradual. Si hay que venderlo, mide tiempo de debugging o bugs regresivos antes/después.
3) Tipar React/Vue como si estuvieras escribiendo Java
Síntoma: genéricos imposibles, tipos kilométricos, DX horrible.
Cómo salir: tipos “suficientes”. Tipa fronteras y props importantes. Si un tipo parece tesis, probablemente estás forzando de más.
4) Creer que TS valida runtime
Síntoma: “pero el tipo dice que siempre viene email”… y en runtime no viene.
Cómo salir: TS no valida runtime. Para inputs externos, usa validación (Zod, Valibot, Yup, lo que uses) o type guards.
Ejemplo con Zod:
import { z } from "zod";
const UserSchema = z.object({
id: z.string(),
profile: z.object({ name: z.string() }).nullable()
});
type User = z.infer<typeof UserSchema>;
function parseUser(data: unknown): User {
return UserSchema.parse(data);
}
5) “Los tipos están bonitos, pero el build se hizo lento”
Síntoma: CI tarda más y el dev server se siente pesado.
Cómo salir:
- Deja que el bundler transpile (SWC/esbuild) y corre el type-check aparte.
- En CI usa
tsc --noEmit. - Si el repo ya creció (monorepo), considera project references.

Checklist final (para decidir y para ejecutar)
- ¿Tu app tiene flujos críticos (pagos, auth, data sensible)? Si sí, TS casi siempre.
- ¿Tu equipo crece o rota? TS ayuda en onboardings y refactors.
- ¿Puedes migrar por islas? Empieza por API/models.
- ¿Tu
tsconfiges amable (strict gradual)? - ¿Tienes regla para
any(no usarlo “porque sí”)? - ¿Validas runtime para inputs externos (forms/APIs)?
- ¿Separaste type-check del build para performance?
- ¿Tienes Definition of Done para archivos migrados (sin
@ts-ignoregratis)?
FAQ
1) ¿TypeScript hace mi app más rápida?
No por sí mismo. TypeScript se borra al compilar. Lo que sí hace es bajar loops de debugging, y eso te vuelve más rápido a ti y al equipo.
2) ¿Cuándo me conviene quedarme en JavaScript?
Cuando el proyecto es corto, el dominio es simple (poca data) y el costo de un bug es bajo: landing, prototipo, demo para validar.
3) ¿Qué tan pesado es migrar un proyecto grande?
No es “difícil”; es talacha. La clave es incremental, empezar por fronteras (API/models) y no prender strict a lo bruto.
4) ¿Qué hago con librerías sin tipos?
Busca primero @types/paquete. Si no existe, crea un global.d.ts con typings mínimos o encapsula la librería en un wrapper tipado para que el resto del código no sufra.
5) ¿any está prohibido?
No. Pero debe ser excepción, no estrategia. Si usas any como duct tape, en 2-3 meses vas a estar de regreso en JavaScript… solo que más lento.
Siguiente episodio
El tipado es solo el primer sable láser. El siguiente round: elegir framework sin casarte a ciegas.
React, Vue y Svelte se ven parecidos desde lejos, pero en chamba real pesan otras cosas: equipo, performance, curva de aprendizaje y mantenimiento.
Idea para cerrar bien este post: toma una sola práctica de aquí y conviértela en algo que tu equipo pueda aplicar hoy.
Cuando un artículo aterriza en decisiones reales, deja de ser contenido y se vuelve ventaja.


