Linting, formatting y compatibilidad en JavaScript | Nicolás Garzón
Linters, formatters, type checkers, tests y herramientas de compatibilidad detectan categorías distintas de problemas.
Texto
Copiar formatter → forma del código
linter → patrones y reglas estáticas
TypeScript/JSDoc → contratos de tipos
unit tests → comportamiento en casos
compatibility data → soporte del runtimeUn formatter decide espacios, saltos y presentación.
JavaScript
Copiar const value= { a : 1 , b : 2 } JavaScript
Copiar const value = {
a : 1 ,
b : 2 ,
} ; Reduce discusiones de estilo, pero no sabe si el algoritmo es correcto.
Un linter analiza el código y aplica reglas.
Variables no utilizadas.
Promesas flotantes mediante plugins.
Comparaciones sospechosas.
Acceso inseguro.
Dependencias de hooks en frameworks.
Imports desordenados o ciclos con herramientas.
Patrones de seguridad.
Una advertencia no siempre representa un fallo real. Investiga el propósito de la regla antes de desactivarla.
Debe incluir una razón concreta y el alcance mínimo.
JavaScript
Copiar export default [
js. configs. recommended,
{
rules : {
eqeqeq : "error" ,
} ,
} ,
] ; Una configuración versionada mantiene reglas iguales en editor, CI y equipo.
Algunas reglas necesitan información del type checker.
Await sobre valores no thenable.
Promesas ignoradas.
Operaciones con tipos incompatibles.
Condiciones siempre verdaderas.
El análisis es más costoso; configura proyectos y caches correctamente.
JavaScript puede documentar formas para editores y type checkers.
JavaScript
Copiar
function subtotal ( item ) {
return item. price * item. quantity;
} JSDoc no valida datos durante ejecución.
TypeScript comprueba contratos estáticos y genera JavaScript.
Respuestas de API.
Datos de storage.
Permisos.
Estado de red.
Reglas del dominio no modeladas.
Las fronteras externas continúan necesitando validación runtime.
Una herramienta puede transformar:
JavaScript
Copiar user?. profile?. name; No puede transformar automáticamente toda API ausente:
JavaScript
Copiar fetch;
IntersectionObserver;
structuredClone;
Polyfill.
Fallback.
Carga condicional.
Cambiar requisitos de soporte.
Proyectos pueden declarar navegadores objetivo.
Texto
Copiar last 2 versions
not deadLas consultas concretas dependen de la herramienta y datos actuales. Define objetivos según usuarios reales, no mediante una cadena copiada sin contexto.
Datos como MDN, Can I Use y web-platform Baseline ayudan a conocer disponibilidad.
Versión mínima.
Soporte parcial.
Flags.
Diferencias móviles.
Contexto seguro.
Restricciones de permiso.
JavaScript
Copiar if ( typeof structuredClone === "function" ) {
return structuredClone ( value) ;
} Detectar una propiedad es preferible a adivinar por user agent cuando el contrato permite fallback.
Puede ser necesaria para bugs específicos, pero es frágil:
Strings cambian.
Navegadores imitan otros.
Versión no implica permiso ni capacidad exacta.
Prefiere feature detection y pruebas del comportamiento relevante.
Un polyfill modifica o añade APIs globales.
Tamaño.
Implementación incompleta.
Conflicto con versión nativa futura.
Carga duplicada.
Usa implementaciones mantenidas y carga solo cuando sea necesario.
Una función importada que no modifica globals.
JavaScript
Copiar import structuredCloneFallback from "./clone.js" ; Reduce efectos globales, pero cada consumidor debe usarla explícitamente.
Texto
Copiar format check
↓
lint
↓
typecheck
↓
tests
↓
buildEl orden puede optimizar tiempo, pero todos deben utilizar la misma configuración que el equipo.
Hooks locales ofrecen feedback rápido, pero pueden omitirse. CI es la fuente de verificación obligatoria.
No ejecutes toda una suite enorme en cada commit si vuelve el flujo inutilizable; selecciona checks rápidos localmente y completos en CI.
Herramientas cambian reglas y defaults. Actualiza de forma revisada:
Lee changelog.
Ejecuta autofixes con diff visible.
Separa cambios mecánicos de cambios de comportamiento.
Ajusta CI y editor.
No siempre conviene lintar o formattear output de build, vendor o archivos generados. Define ignores explícitos para evitar ruido.
JavaScript
Copiar button. addEventListener ( "click" , ( ) => {
void save ( ) . catch ( showError) ;
} ) ; Una regla puede exigir que toda promesa sea awaited, retornada o marcada como fire-and-forget con manejo explícito.
Esperar que formatter encuentre bugs.
Desactivar reglas sin entenderlas.
Tener configuración diferente entre editor y CI.
Creer que TypeScript valida JSON runtime.
Confundir transformación de sintaxis con polyfill.
Copiar targets sin conocer usuarios.
Usar user-agent para todo.
Cargar polyfills globales innecesarios.
Confiar solo en hooks locales.
Mezclar autofix masivo con lógica nueva.
Cada herramienta detecta problemas diferentes.
Formatter estandariza forma.
Linter analiza patrones estáticos.
Tipos no validan datos externos por sí solos.
Syntax transform y API polyfill son conceptos distintos.
Los targets deben reflejar entornos reales.
Feature detection suele ser más robusta que user-agent.
CI mantiene el contrato compartido.
Desactivar una regla necesita justificación localizada.
¿Por qué compilar optional chaining no hace que IndexedDB exista en un runtime que no la implementa?
Respuesta Porque optional chaining es sintaxis transformable. IndexedDB es una API del host y necesita soporte o una alternativa de diseño.
Leer documentación y especificaciones explica cómo encontrar el contrato correcto y distinguir estándar, host y herramienta.