Reglas ESLint esenciales
Configura las reglas ESLint más impactantes para React, hooks, TypeScript, importaciones y accesibilidad.
Busca en todas las páginas de la documentación
Configura las reglas ESLint más impactantes para React, hooks, TypeScript, importaciones y accesibilidad.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Tarjeta de referencia rápida - lista para copiar y pegar.
// Niveles de severidad
"off" // 0 - desactiva la regla
"warn" // 1 - advertencia amarilla, no falla CI
"error" // 2 - error rojo, falla CI y bloquea compilaciones
// Patrón común: anular una regla
{
rules: {
"rule-name": "error",
"rule-name": ["error", { option: "value" }],
},
}Cuándo usarlo: Cuando los preajustes predeterminados son demasiado flexibles o estrictos y necesitas afinar reglas específicas.
// eslint.config.mjs
import { FlatCompat } from "@eslint/eslintrc";
import { dirname } from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const compat = new FlatCompat({ baseDirectory: __dirname });
const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"),
{
rules: {
// --- Reglas React ---
"react/jsx-no-target-blank": "error",
"react/no-unescaped-entities": "off",
"react/self-closing-comp": "warn",
"react/jsx-curly-brace-presence": [
"warn",
{ props: "never", children: "never" },
],
// --- Reglas hooks ---
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
// --- Reglas TypeScript ---
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/consistent-type-imports": [
"error",
{ prefer: "type-imports" },
],
// --- Reglas de importación ---
"import/order": [
"warn",
{
groups: [
"builtin",
"external",
"internal",
["parent", "sibling"],
"index",
"type",
],
"newlines-between": "always",
alphabetize: { order: "asc", caseInsensitive: true },
},
],
"import/no-duplicates": "error",
// --- Reglas de accesibilidad ---
"jsx-a11y/alt-text": "error",
"jsx-a11y/anchor-is-valid": "warn",
},
},
];
export default eslintConfig;Lo que esto demuestra:
error (debe corregirse) y warn (debería corregirse)_"off", "warn" o "error"["error", { option: true }]next/core-web-vitals ya habilita muchas reglas - las anulas en tu propia configuraciónreact/, @typescript-eslint/)Reglas React que vale la pena conocer:
| Regla | Qué captura |
|---|---|
react/jsx-no-target-blank | Falta rel="noreferrer" en enlaces con target="_blank" |
react/no-unescaped-entities | ' o " sin escapar en texto JSX |
react/self-closing-comp | <div></div> en lugar de <div /> para elementos vacíos |
react/jsx-curly-brace-presence | {"string"} innecesario en lugar de string en JSX |
react/no-array-index-key | Usar índice de array como prop key |
Reglas hooks:
| Regla | Qué captura |
|---|---|
react-hooks/rules-of-hooks | Hooks llamados condicionalmente o en bucles |
react-hooks/exhaustive-deps | Dependencias faltantes en useEffect, useMemo, useCallback |
Reglas TypeScript que vale la pena habilitar:
| Regla | Qué captura |
|---|---|
@typescript-eslint/no-unused-vars | Variables declaradas pero sin usar |
@typescript-eslint/no-explicit-any | Usar tipo any |
@typescript-eslint/consistent-type-imports | Falta la palabra clave type en importaciones solo-tipo |
@typescript-eslint/no-non-null-assertion | Usar afirmación ! de no-null |
@typescript-eslint/prefer-nullish-coalescing | Usar OR lógico en lugar de ?? |
// consistent-type-imports fuerza esto:
import type { User } from "@/types"; // importación solo-tipo
import { fetchUser } from "@/lib/api"; // importación de valor
// En lugar de mezclarlos:
import { User, fetchUser } from "@/lib/api"; // ❌ error de lintCosas que te morderán. Cada trampa incluye qué sale mal, por qué sucede y la solución.
Falsos positivos de exhaustive-deps - Esta regla a veces marca referencias estables como dispatch o refs. Solución: Usa // eslint-disable-next-line react-hooks/exhaustive-deps solo cuando estés seguro de que la dependencia es estable. Nunca la desactives globalmente.
Conflictos de no-unused-vars con TypeScript - La regla base de ESLint no-unused-vars y @typescript-eslint/no-unused-vars pueden entrar en conflicto. Solución: Desactiva la regla base y usa solo la versión de TypeScript: "no-unused-vars": "off".
import/order sin auto-corrección - La regla reporta violaciones pero --fix solo funciona para reordenar, no para agregar saltos de línea entre grupos retroactivamente. Solución: Ejecuta eslint --fix y agrega manualmente saltos de línea en el primer paso.
La severidad importa para CI - Usar "warn" significa que CI pasa incluso con violaciones. Si quieres forzar una regla, usa "error". Solución: Reserva "warn" para reglas hacia las que te estás migrando, usa "error" para reglas forzadas.
Otras formas de resolver el mismo problema - y cuándo es mejor cada una.
| Alternativa | Úsalo cuando | No lo uses cuando |
|---|---|---|
Valores predeterminados de next/core-web-vitals | Deseas valores predeterminados sensatos sin personalización | Necesitas reglas más estrictas o específicas del proyecto |
| Reglas de lint de Biome | Deseas linting más rápido con reglas integradas | Necesitas el rango completo de plugins de ESLint |
Compilador TypeScript (tsc --noEmit) | Deseas verificaciones de nivel de tipo que ESLint no puede hacer | Necesitas enforcement de estilo de código o patrones |
"off" (0) desactiva la regla completamente."warn" (1) muestra una advertencia amarilla pero no falla CI ni bloquea compilaciones."error" (2) muestra un error rojo, falla CI y bloquea compilaciones.no-unused-vars no entiende la sintaxis de TypeScript (interfaces, alias de tipo, enums)."no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],// Forzado (correcto):
import type { User } from "@/types";
import { fetchUser } from "@/lib/api";
// Rechazado (error de lint):
import { User, fetchUser } from "@/lib/api";Separa las importaciones solo-tipo de las importaciones de valor para que los bundlers puedan hacer tree-shake de tipos.
"newlines-between": "always".eslint --fix puede reordenar importaciones dentro de grupos.eslint --fix una vez, luego agrega manualmente saltos de línea en el primer paso."warn" para reglas hacia las que te estás migrando o que son de carácter consultivo."error" para reglas que deseas forzar estrictamente en CI."warn" no fallará CI, por lo que las violaciones se acumulan silenciosamente si olvidas promocionar a "error".useEffect, useMemo y useCallback."warn" porque puede producir falsos positivos con referencias estables como dispatch.// eslint-disable-next-line react-hooks/exhaustive-deps solo cuando estés seguro de que la dependencia es estable.target="_blank" sin rel="noreferrer" exponen tu página a ataques window.opener.rel="noreferrer" a todos los enlaces externos.// Solo severidad:
"rule-name": "error"
// Severidad con opciones:
"rule-name": ["error", { option: "value" }]El segundo elemento del array es el objeto de opciones de la regla.
| Regla | Propósito |
|---|---|
@typescript-eslint/no-explicit-any | Marca el uso de any |
@typescript-eslint/no-non-null-assertion | Marca afirmaciones ! |
@typescript-eslint/prefer-nullish-coalescing | Prefiere ?? sobre || |
@typescript-eslint/consistent-type-imports | Fuerza import type |
rules después del array extends en tu configuración plana.const eslintConfig = [
...compat.extends("next/core-web-vitals"),
{ rules: { "react/no-unescaped-entities": "off" } },
];Revisado por Chris St. John·Última actualización: 16 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥