La mayoría de los proyectos TypeScript que analizo tienen "strict": true en el tsconfig.json, pero también tienen // @ts-ignore esparcidos por el código, any en lugares estratégicos e ingenieros que no saben qué protege el strict mode.
Strict mode no es un conjunto arbitrario de restricciones para irritar al compilador. Son flags, cada una capturando una categoría de bug que ocurre en runtime. Entender qué hace cada flag cambia "el TypeScript me obligó a hacer esto" a "el TypeScript me impidió cometer ese error".
Qué habilita "strict": true
"strict": true es un atajo para habilitar un conjunto de flags. Vamos con lo que importa:
strictNullChecks
La más importante. Sin ella, null y undefined son asignables a cualquier tipo. Con ella, necesitas lidiar con la posibilidad de ausencia.
// Sin strictNullChecks: compila, puede explotar en runtime
function getUser(id: string): User {
return db.find(id) // puede retornar undefined
}
const name = getUser('123').name // TypeError: Cannot read property 'name' of undefined
// Con strictNullChecks: error en tiempo de compilación
function getUser(id: string): User | undefined {
return db.find(id)
}
const user = getUser('123')
const name = user?.name // forzado a lidiar con el undefined
noImplicitAny
Fuerza el tipado explícito cuando TypeScript no puede inferir el tipo. Sin esto, los parámetros de función sin tipo se vuelven any sin aviso, y pierdes toda la protección del sistema de tipos.
// ❌ Sin noImplicitAny: param es `any` implícitamente
function process(data) { // param: any
return data.value.toUpperCase() // sin verificación
}
// ✅ Con noImplicitAny: declaras la intención
function process(data: { value: string }) {
return data.value.toUpperCase()
}
strictFunctionTypes
Garantiza verificación de tipos correcta en callbacks. Sin ella, las funciones se verifican bivariantly, lo que puede dejar pasar bugs de tipo.
// strictFunctionTypes captura este bug
type Handler = (event: MouseEvent) => void
const myHandler: Handler = (event: Event) => {} // ❌ Error correcto: MouseEvent es más específico
strictPropertyInitialization
Garantiza que las propiedades de clase se inicialicen en el constructor. Previene lecturas de propiedades undefined que parecen definidas.
class UserService {
private db: Database // ❌ Error: no inicializado en el constructor
constructor() {
// olvidaste inicializar db
}
}
// ✅ Correcto
class UserService {
private db: Database
constructor(db: Database) {
this.db = db
}
}
Flags que no están en strict pero deberías habilitar
noUncheckedIndexedAccess
Los accesos a arrays y objetos con índice retornan T | undefined en lugar de T. Previene uno de los bugs más comunes: asumir que un índice siempre existe.
// tsconfig.json
{ "compilerOptions": { "noUncheckedIndexedAccess": true } }
const items = ['a', 'b', 'c']
const first = items[0] // tipo: string | undefined (no string)
const safe = first?.toUpperCase() // forzado a verificar
exactOptionalPropertyTypes
Diferencia { prop?: string } (prop puede estar ausente) de { prop: string | undefined } (prop presente pero undefined). Son cosas diferentes, y sin esa flag, TypeScript las trata igual.
Cómo migrar un proyecto legado a strict
Habilitar strict de una sola vez en un proyecto grande no es práctico. La estrategia que funciona:
- Habilita
"strict": truey usa// @ts-ignoreen todo lo que se rompa (sí, temporalmente) - Crea una regla de lint que prohíba nuevos
// @ts-ignore, el legado puede existir, lo nuevo no - Gradualmente, resuelve los
@ts-ignorearchivo por archivo, priorizando los más críticos
Esto da el beneficio inmediato de strict en el código nuevo mientras el legado se corrige poco a poco.
Por qué no deshabilitar lo que no entiendes
Cada vez que agregas // @ts-ignore, as any, o deshabilitas una flag, estás diciendo: "Confío en mí mismo más que en el compilador aquí." A veces eso es legítimo, por ejemplo al trabajar con librerías mal tipadas.
La mayoría de las veces, es escape. Y el TypeScript te está protegiendo de algo que va a explotar en runtime. Quizás no mañana. Quizás en 6 meses. Quizás en producción un viernes a las 23h.
Cuando no entiendes por qué el TypeScript se está quejando, la respuesta correcta es entender, no silenciar. Usar TypeScript y usar TypeScript bien son cosas diferentes.
¿Te gustó el contenido?
Construyo productos web y soluciones con IA de la manera correcta — arquitectura sólida, código sostenible y entrega real.
Hablemos