Menu

Modo strict en TypeScript: qué activa strict: true

strict: true en tsconfig.json activa una familia de comprobaciones de tipos: noImplicitAny, strictNullChecks, strictPropertyInitialization y cinco más. Mira qué detecta cada una, cómo activar el modo strict en un proyecto existente y las opciones útiles que strict no incluye.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

El modo strict es la opción "strict": true de tsconfig.json. Es un único interruptor para ocho opciones de comprobación de tipos que detectan any implícitos, null y undefined sin comprobar, asignaciones de funciones inseguras y campos de clase sin inicializar. En TypeScript 7, strict está activado por defecto. Así es el código que lo supera:

La salida es no user, SyntaxError y 42. Quita el : number, el ?. o la comprobación con instanceof y el archivo deja de compilar.

Cómo activarlo

{
    "compilerOptions": {
        "strict": true
    }
}

Las opciones individuales ganan a strict, en cualquier dirección. "strict": true, "strictNullChecks": false mantiene todo excepto la comprobación de null; "strict": false, "noImplicitAny": true activa solo esa. strict también te incluye en las comprobaciones que se añadan en versiones futuras, porque las nuevas opciones de la familia strict se suman al grupo.

El strict de TypeScript no tiene nada que ver con la directiva "use strict" de JavaScript, que es un modo de ejecución. TypeScript 7 siempre genera "use strict" donde hace falta, y poner alwaysStrict: false es el error TS5108 (la opción se eliminó).

Qué detecta cada opción

OpciónQué informaError
noImplicitAnyun parámetro o variable cuyo tipo sería any sin avisarTS7006 Parameter 'x' implicitly has an 'any' type.
strictNullChecksusar un valor que puede ser null o undefinedTS18048 'u' is possibly 'undefined'.
strictFunctionTypesasignar una función cuyo tipo de parámetro es más estrecho de lo requeridoTS2322
strictBindCallApplyargumentos incorrectos en .call, .bind y .applyTS2345
strictPropertyInitializationun campo de clase que nunca se asignaTS2564 Property 'name' has no initializer and is not definitely assigned in the constructor.
noImplicitThisthis con tipo any implícito, como en una function anidadaTS2683
useUnknownInCatchVariablesusar una variable de catch antes de estrecharla (es unknown)TS18046 'err' is of type 'unknown'.
strictBuiltinIteratorReturntratar it.next().value de un iterador integrado como si siempre estuviera definidoTS2322

Las dos que más código cambian son noImplicitAny y strictNullChecks. Este bloque incumple las dos a propósito:

Imprime index.ts(2,17): error TS7006: Parameter 'x' implicitly has an 'any' type. y index.ts(11,13): error TS18048: 'user' is possibly 'undefined'. Sin strict, esto compila y luego falla en tiempo de ejecución con TypeError: Cannot read properties of undefined (reading 'name'). Con strict, el fallo pasa a ser un error de compilación. Las soluciones son el primer bloque de esta página.

strictFunctionTypes: por qué existe

Una función que solo maneja strings no se debe usar donde pueden llegar números. La comprobación de abajo está silenciada con @ts-expect-error para que puedas ejecutarla y ver qué evita el error:

Sin el comentario, la asignación es el error TS2322, Type '(s: string) => void' is not assignable to type 'Handler'., seguido de Types of parameters 's' and 'value' are incompatible. Queda una excepción por diseño: los parámetros de los métodos declarados con sintaxis de método (handle(value: string | number): void dentro de una interfaz) se siguen comprobando de la forma más laxa, así que shout podría asignarse a un método así sin error.

strictPropertyInitialization

Cada campo de clase debe recibir un valor en su declaración o en el constructor. Tres formas de cumplirlo:

Salida:

Account {
  owner: 'Ada',
  balance: 0,
  history: [],
  lastLogin: undefined,
  sessionId: 's-1'
}

Las propiedades lastLogin y sessionId existen con el valor undefined porque los campos de clase son campos reales de JavaScript con target ES2022. El ! quita la comprobación sin añadir ninguna protección en tiempo de ejecución, así que es preferible usar las otras formas. Esta opción necesita strictNullChecks; si lo desactivas, también se desactiva ella.

Activar strict en un proyecto existente

Pasar un proyecto grande a strict de golpe puede producir cientos de errores. Como strict es el valor por defecto en TypeScript 7, actualizar un proyecto cuyo tsconfig.json nunca mencionó strict lo activa por sí solo; escribe "strict": false si necesitas el comportamiento anterior mientras migras. Un camino que mantiene la compilación en verde:

  1. Añade "strict": true y desactiva las opciones con más errores, normalmente "strictNullChecks": false y "noImplicitAny": false.
  2. Corrige los errores que quedan, luego activa una opción más y repite.
  3. Para noImplicitAny, la mayoría de las correcciones son anotaciones de parámetros. Para strictNullChecks, añade | undefined donde los valores pueden faltar y luego manéjalo con ?., ?? o un if.
  4. Cuando una corrección tenga que esperar, pon // @ts-expect-error con un motivo en la línea. A diferencia de @ts-ignore, da un error en cuanto el problema desaparece, así que la lista se reduce sola.

No recurras a as any ni a ! para silenciar errores en masa: cada uno oculta justo el bug que la opción se añadió para encontrar.

Opciones útiles que strict no incluye

Son independientes porque rechazan código que a menudo es correcto. Muchos proyectos las activan de todos modos.

OpciónQué hace
noUncheckedIndexedAccessarr[i] y record[key] incluyen undefined en su tipo
exactOptionalPropertyTypesdebug?: boolean acepta una clave ausente pero no debug: undefined
noImplicitReturnscada camino de una función que devuelve un valor debe hacer return (TS7030)
noImplicitOverrideun método que sobrescribe un método base debe indicar override (TS4114)
noFallthroughCasesInSwitchun case no vacío debe terminar con break, return o throw (TS7029)
noUnusedLocals, noUnusedParameterslas variables y los parámetros sin usar son errores
noPropertyAccessFromIndexSignaturelas claves de una firma de índice deben usar obj["key"], no obj.key

noUncheckedIndexedAccess es la que detecta más bugs reales. Con ella activada:

const scores = [90, 85];
const d: Record<string, number> = {};

const third: number = scores[2]; // error TS2322: Type 'number | undefined' is not assignable to type 'number'.
const c: number = d["x"];        // same error

const safe = scores[2] ?? 0;     // number
for (const s of scores) {        // for...of is not affected: s is number
    console.log(s);
}

tsc --init en TypeScript 7 activa noUncheckedIndexedAccess y exactOptionalPropertyTypes en la configuración que genera, junto a strict.

Preguntas frecuentes

¿Qué hace el modo strict en TypeScript?

"strict": true activa un grupo de comprobaciones más estrictas: noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables y strictBuiltinIteratorReturn. Juntas impiden que aparezca any sin avisar y hacen que null y undefined formen parte del sistema de tipos.

¿El modo strict está activado por defecto en TypeScript?

En TypeScript 7, sí: strict vale true por defecto, así que un proyecto sin ninguna configuración de strict tiene todas las comprobaciones estrictas. tsc --init también escribe "strict": true de forma explícita. Para desactivarlo tienes que escribir "strict": false.

¿Puedo desactivar una comprobación estricta y mantener el resto?

Sí. Las opciones individuales tienen prioridad sobre strict: { "strict": true, "strictNullChecks": false } mantiene todas las comprobaciones estrictas excepto la de null. Es la forma habitual de migrar un proyecto grande opción por opción.

¿El modo strict de TypeScript es lo mismo que "use strict" de JavaScript?

No. "use strict" es un modo de ejecución de JavaScript que cambia cómo se comporta el código. El strict de TypeScript solo cambia lo que informa el comprobador de tipos. TypeScript 7 siempre genera "use strict" en la salida que no es de módulo, y alwaysStrict: false es ahora una opción eliminada.

¿strict incluye noUncheckedIndexedAccess?

No. noUncheckedIndexedAccess, exactOptionalPropertyTypes, noImplicitReturns, noImplicitOverride y noFallthroughCasesInSwitch son opciones aparte que activas tú. tsc --init activa las dos primeras en la configuración que genera.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR