Patrones de Modo Estricto
Receta
Escribe código React que prospera bajo la configuración más estricta de TypeScript. Domina patrones para strictNullChecks, noUncheckedIndexedAccess y exactOptionalPropertyTypes para detectar errores que configuraciones más flexibles pierden.
Ejemplo Funcional
// strictNullChecks: manejo seguro de valores anulables
type User = {
id: string;
name: string;
address?: {
street: string;
city: string;
};
};
function UserAddress({ user }: { user: User }) {
// Sin strictNullChecks, esto devuelve silenciosamente undefined
// Con strictNullChecks, TypeScript te obliga a manejar el caso
if (!user.address) {
return <p>Sin dirección registrada</p>;
}
return (
<p>
{user.address.street}, {user.address.city}
</p>
);
}// noUncheckedIndexedAccess: acceso seguro a arrays y objetos
const colors = ["red", "green", "blue"];
// Sin noUncheckedIndexedAccess: colors[5] es string
// Con noUncheckedIndexedAccess: colors[5] es string | undefined
function getColor(index: number): string {
const color = colors[index];
if (!color) {
return "default";
}
return color; // TypeScript ahora sabe que esto es string, no string | undefined
}// Acceso seguro a registros
type FeatureFlags = Record<string, boolean>;
function isFeatureEnabled(flags: FeatureFlags, key: string): boolean {
const value = flags[key];
// Con noUncheckedIndexedAccess, value es boolean | undefined
return value ?? false;
}Análisis Profundo
Cómo Funciona
strict: truehabilita una familia de comprobaciones estrictas. Las más impactantes para React sonstrictNullChecks,strictFunctionTypesynoImplicitAny.strictNullCheckshace quenullyundefinedsean tipos distintos que deben manejarse explícitamente. Una variable tipada comostringno puede sernulla menos que esté tipada comostring | null.noUncheckedIndexedAccessañade| undefineda cualquier acceso de índice en arrays y registros. Esto detecta el error común de acceder a un índice de array que podría estar fuera de rango.exactOptionalPropertyTypesdistingue entre una propiedad ausente y una explícitamenteundefined.{ name?: string }significa "name puede estar ausente" pero no{ name: undefined }.strictFunctionTypesimpone comprobación de parámetros contravariante en tipos de función. Esto detecta errores sutiles con tipos de manejador de eventos y props de callback.
Variaciones
Búsquedas seguras de mapa/objeto:
const userMap = new Map<string, User>();
function getUser(id: string): User {
const user = userMap.get(id); // User | undefined
if (!user) {
throw new Error(`User ${id} not found`);
}
return user; // Estrechado a User
}Aserción no-null como escape hatch:
// Úsalo raramente y solo cuando tengas la certeza de que el valor existe
const canvas = document.getElementById("canvas") as HTMLCanvasElement;
const ctx = canvas.getContext("2d")!; // Aserción no-null
// Mejor: guardia y lanzar excepción
const ctx2 = canvas.getContext("2d");
if (!ctx2) throw new Error("Canvas 2D context not available");Manejo de encadenamiento opcional con nulls estrictos:
type Config = {
api?: {
baseUrl?: string;
timeout?: number;
};
};
function getApiUrl(config: Config): string {
return config.api?.baseUrl ?? "https://api.example.com";
}exactOptionalPropertyTypes en acción:
// Con exactOptionalPropertyTypes habilitado:
type Settings = {
theme?: "light" | "dark";
};
// Permitido
const a: Settings = {};
const b: Settings = { theme: "light" };
// Error: undefined no es asignable a "light" | "dark"
// const c: Settings = { theme: undefined };Notas de TypeScript
- Habilita estos incrementalmente si estás migrando: primero
strict: true, luegonoUncheckedIndexedAccess, luegoexactOptionalPropertyTypes. - Los operadores
??(coalescencia nula) y?.(encadenamiento opcional) son tus mejores herramientas bajo configuraciones estrictas. Manejannull | undefinedlimpiamente. Array.prototype.find()devuelveT | undefinedincluso sinnoUncheckedIndexedAccess. La configuración afecta principalmente al acceso entre corchetesarr[i].
Trampas
noUncheckedIndexedAccessañade| undefinedtambién al acceso a tuplas. Para tuplas con longitud conocida, esto puede parecer demasiado cauteloso. Usa desestructuración en su lugar:const [first, second] = tuple.exactOptionalPropertyTypesrompe código que explícitamente pasaundefinedpara limpiar campos opcionales. Puede que necesites usardelete obj.fielden su lugar.- Las aserciones no-null (
!) eluden las comprobaciones estrictas completamente. Cada!es un potencial fallo en tiempo de ejecución. Prefiere guardias y estrechamiento. - Los tipos de bibliotecas de terceros pueden no ser compatibles con tus configuraciones estrictas.
skipLibCheck: trueayuda, pero oculta problemas en tus propios archivos.d.ts.
Alternativas
| Enfoque | Ventajas | Desventajas |
|---|---|---|
strict: true + noUncheckedIndexedAccess | Máxima seguridad, detecta la mayoría de errores | Manejo de null más verboso |
strict: true solamente | Buen balance entre seguridad y conveniencia | Pierde errores de array fuera de rango |
strict: false con flags incrementales | Ruta de migración gradual | Fácil perder comprobaciones importantes |
| Validación en tiempo de ejecución (Zod) | Detecta problemas que modo strict no puede | Dependencia añadida, overhead en tiempo de ejecución |
Aserciones as para eludir strictness | Corrección rápida para errores de tipo | Anula el propósito del modo strict |
Preguntas Frecuentes
¿Qué comprobaciones habilita strict: true en TypeScript?
strictNullChecks,strictFunctionTypes,noImplicitAny,strictBindCallApply,strictPropertyInitializationy otras.- Es una familia de flags, no una comprobación única.
- Las más impactantes para React son
strictNullChecks,strictFunctionTypesynoImplicitAny.
¿Cómo cambia strictNullChecks la forma en que escribes componentes React?
- Una variable tipada como
stringya no puede sernulloundefineda menos que esté explícitamente tipada comostring | null. - Debes manejar el caso anulable con guardias, encadenamiento opcional o coalescencia nula.
- Sin él, los errores de acceso null/undefined son silenciosos.
¿Qué hace noUncheckedIndexedAccess?
- Añade
| undefineda cualquier acceso de índice en arrays y registros. colors[5]se convierte enstring | undefineden lugar destring.- Detecta el error común de acceder a un índice de array fuera de rango.
¿Cuál es la diferencia entre una propiedad ausente y una establecida en undefined bajo exactOptionalPropertyTypes?
type Settings = { theme?: "light" | "dark" };
const a: Settings = {}; // OK: propiedad ausente
const b: Settings = { theme: "light" }; // OK
// const c: Settings = { theme: undefined }; // ERROR- Una propiedad ausente y
undefinedse tratan como distintas. - No puedes asignar explícitamente
undefineda un campo opcional.
¿Por qué es arriesgado el operador de aserción no-null (!) bajo modo strict?
- Elude las comprobaciones estrictas de null completamente, diciéndole a TypeScript "confía en mí, esto no es null."
- Cada
!es un potencial fallo en tiempo de ejecución si el valor realmente es null o undefined. - Prefiere guardias, encadenamiento opcional (
?.) o coalescencia nula (??) en su lugar.
Trampa: ¿noUncheckedIndexedAccess afecta tuplas?
- Sí. Incluso las tuplas con longitud conocida obtienen
| undefineden acceso entre corchetes. - Esto puede parecer demasiado cauteloso para tuplas.
- Usa desestructuración en su lugar:
const [first, second] = tupleevita el| undefined.
¿Cómo deberías manejar búsquedas seguras de arrays y registros bajo configuraciones estrictas?
const colors = ["red", "green", "blue"];
function getColor(index: number): string {
const color = colors[index]; // string | undefined
if (!color) return "default";
return color; // estrechado a string
}- Siempre verifica
undefineddespués del acceso de índice. - Usa
??para proporcionar valores de fallback.
¿Cuál es el orden recomendado para habilitar flags estrictos incrementalmente?
- Primero:
strict: true(habilita la familia de comprobaciones centrales). - Segundo:
noUncheckedIndexedAccess(añade seguridad de índice). - Tercero:
exactOptionalPropertyTypes(manejo de propiedades opcionales más estricto).
Trampa: ¿Pueden los tipos de bibliotecas de terceros romperse bajo tus configuraciones estrictas?
- Sí. Las bibliotecas pueden no estar escritas con
strictNullChecksoexactOptionalPropertyTypesen mente. skipLibCheck: trueayuda saltándose la comprobación de tipos de archivos.d.ts.- Pero esto también oculta errores en tus propios archivos
.d.ts.
¿Cuál es la diferencia entre ?. (encadenamiento opcional) y ?? (coalescencia nula)?
?.cortocircuita aundefinedsi el lado izquierdo esnulloundefined:config.api?.baseUrl.??proporciona un fallback solo paranulloundefined:value ?? "default".- A diferencia de
||,??no se activa en valores falsy como0o"".