# ESLint

## Hvad det er

ESLint er et open source-værktøj til statisk analyse, der læser kildekoden i et
JavaScript-projekt, holder den op mod et sæt konfigurerede regler og melder
hvert sted, hvor koden bryder en af dem, og som selv retter de enkle tilfælde,
når man beder om det. På kommandolinjen hedder det `eslint`, og det installeres
fra npm som en udviklingsafhængighed i det projekt, det skal tjekke. Nicholas C.
Zakas startede projektet i juni 2013, og det præsenterer sig stadig som en
JavaScript-linter, man kan konfigurere.

Selve programmet bliver aldrig kørt. En parser omdanner hver fil til et abstrakt
syntakstræ i ESTree-formatet, og hver regel er et lille modul, der beder om at
blive kaldt ved bestemte slags knuder: hver funktion, hver sammenligning, hvert
`await`. Reglen ser på det, den får udleveret, og hvis noget er galt, melder den
en besked og en placering. Nogle regler har en rettelse med, en ændring som
projektet kun godtager, hvis den fjerner problemet uden at ændre, hvad
programmet gør, og `eslint --fix` skriver dem direkte ind i filerne. Andre
regler kommer i stedet med forslag. De kan ændre adfærd og bliver derfor anvendt
ét ad gangen, af et menneske, i en editor.

Næsten alt omkring kernen kan skiftes ud. Plugins er npm-pakker, der tilføjer
regler, delbare konfigurationer, processorer eller understøttelse af andre
sprog. En anden parser lader ESLint læse syntaks, som standardparseren ikke
forstår, for eksempel TypeScript. Processorer trækker JavaScript ud af andre
filer, som kodeblokkene i et Markdown-dokument, og formatters bestemmer, hvordan
rapporten skrives ud. I projektets egen beskrivelse af sin filosofi står hver
regel for sig selv, kan slås fra og kan sættes til at advare eller fejle efter
behov.

Det hele samles i én JavaScript-fil i roden af projektet, typisk
`eslint.config.js` eller varianterne `.mjs` og `.cjs`, som eksporterer et array
af objekter. Hvert objekt angiver, hvilke filer det gælder for, og hvilke
regler, globale variabler og parserindstillinger der gælder for dem, og senere
objekter overskriver tidligere. Den opbygning, kaldet flat config, blev standard
med ESLint v9.0.0 den 5. april 2024. ESLint v10.0.0, udgivet den 6. februar
2026, fjernede det gamle `.eslintrc`-format og `.eslintignore`-filen helt.

## Hvorfor det betyder noget

En linter gør kun nytte i ét øjeblik: når den stopper en ændring, før den bliver
merget. ESLint træffer den afgørelse gennem sin exitkode, og exitkoden følger
reglernes alvorsgrad. Hver regel står til `"off"`, `"warn"` eller `"error"`. En
fejl får kommandoen til at afslutte med 1. En advarsel bliver skrevet ud, og
kommandoen afslutter alligevel med 0, medmindre `--max-warnings` sætter et loft,
og det loft er slået fra som standard. Exitkode 2 er forbeholdt en ødelagt
konfiguration eller et internt nedbrud.

Den egentlige beslutning, et team træffer med ESLint, er derfor, hvad en
advarsel skal betyde. En advarsel, der aldrig får et build til at fejle, er et
råd, og råd i en terminal bliver scrollet forbi, så snart der står fyrre linjer
af dem. Teams, der vil have linteren til at stå fast, sætter enten hver regel,
de går op i, til `"error"`, eller kører kvalitetsporten med `--max-warnings 0`.
Begge veje er outputtet på en sund branch blankt, og en enkelt ny linje er en
nyhed, som nogen faktisk læser.

Gevinsten ligger i det, JavaScript lader slippe igennem. Sproget indlæser uden
protester en fil, der bruger en variabel, ingen har erklæret, definerer den
samme nøgle to gange i et objekt, sammenligner en værdi med `NaN` via `===`
eller har kode efter et `return`, som aldrig kan nås. Hver af dem fejler først,
når netop den linje udføres, og det kan meget vel være i produktion. Reglerne i
ESLints anbefalede sæt fanger alle fire før review, så den, der læser ændringen,
kan bruge tiden på designet.

Der er en pris. En konfiguration samler holdninger op, og en regel, der slår ud
på korrekt kode, lærer folk at holde op med at læse outputtet, hvilket er værre
end slet ingen regel. En linter er desuden kun så god som det tidspunkt, den
kører på: kører den kun i en editor på nogle af maskinerne, tjekker den noget af
koden noget af tiden.

## Sådan ser det ud i praksis

ESLint var én af seks lintere bag
[en zero-warnings-grænse på tværs af seks sprog](/da/portfolio/set-a-zero-warnings-quality-bar-across-six-79/),
hvor det tjekkede TypeScript ved siden af golangci-lint til Go, SQLFluff til
SQL, Ruff til Python, ShellCheck til shellscripts og markdownlint til Markdown.
Det, der fik grænsen til at holde, var netop spørgsmålet om alvorsgrad, afgjort
én gang for alle: hver linterdiagnostik er en fejl, der findes intet
»warn«-niveau at gemme sig i, og inline-undertrykkelser er forbudt. Pre-commit-
og pre-push-hooks kører linterne og testene, så en commit, der ville tilføje et
problem, bliver afvist, før den findes.

Samme repository fik siden brug for regler, som ingen udgivet pakke indeholder:
dem om, hvordan netop den kodebase skal fungere.
[Femten egne ESLint-regler holder husets mønstre på plads i TypeScript](/da/portfolio/built-the-repository-s-guard-engine-of-268-checks-95/)
ved siden af 274 check-scripts, hvoraf 268 er registreret i commit-hooks. Én af
valideringerne tjekker, at ingen i al stilhed har tilføjet en
inline-undertrykkelse. Selve guard-laget har 146 test, fordi en ødelagt guard
lader alt passere, uden at nogen opdager det, og siden siger prisen ligeud: det
er langsomt at committe.

Dette site holder sine egne build-scripts op mod samme standard i mindre skala.
Dets `eslint.config.mjs` tager udgangspunkt i `js.configs.recommended` og
tilføjer kun regler, som koden allerede bestod, da de blev målt. Kommentarerne
beskriver en ny måling den 15. oktober 2026 over alle 199 regler, der ikke er
udfasede, og den slog 21 regler mere til, alle om korrekthed frem for smag. Hver
regel er en fejl. `reportUnusedDisableDirectives`, der som standard er en
advarsel, er også hævet til fejl, så en disable-kommentar, der ikke længere
undertrykker noget, får kørslen til at fejle. Scriptene erklærer både Node- og
browserglobaler, fordi de funktionskroppe, de giver videre til `page.evaluate`,
kører inde i en browser, få linjer fra kode, der kører i Node.

## Hvor det går galt

Det meste besvær med ESLint er linteren, der gør præcis, hvad konfigurationen
siger, og det er ikke altid det, teamet tror, den siger.

**Buildet er grønt, og terminalen er fuld af advarsler.** Advarsler lader
exitkoden stå på 0, så CI går igennem, mens listen vokser med et par linjer om
ugen, og til sidst står en rigtig fejl i den uden at blive læst. Beslut, hvilke
regler der betyder noget, sæt dem til `"error"`, slå resten fra, og føj
`--max-warnings 0` til kvalitetsporten, så advarsler holder op med at hobe sig
op.

**En disable-kommentar overlever sin grund.** En linje blev gjort tavs af en god
grund engang. Koden under den ændrede sig, kommentaren blev stående, og nu
skjuler den det næste problem på linjen eller slet ingenting. Sæt
`linterOptions.reportUnusedDisableDirectives` til `"error"`, så direktiver, der
intet undertrykker, får kørslen til at fejle, og kræv en begrundelse efter `--`
på dem, der bliver tilbage, så den, der reviewer, kan vurdere dem:

```js
// eslint-disable-next-line no-console -- udskriften er CLI'ets output
console.log(report);
```

**En opgradering ændrer, hvilke filer der bliver tjekket.** Efter skiftet til
v10 bliver stier, som `.eslintignore` før sprang over, pludselig rapporteret,
eller én mappe begynder at følge andre regler. Version 10 respekterer hverken
`.eslintrc.*` eller `.eslintignore`, og den leder efter `eslint.config.*` fra
mappen for hver fil, der lintes, så en glemt konfiguration i en undermappe nu
styrer netop den undermappe. Flyt ignoreringerne ind i et globalt
`ignores`-objekt, konvertér den gamle fil med
`npx @eslint/migrate-config .eslintrc.json` og gennemgå resultatet, og find
derefter hver `eslint.config.*` i træet og fjern dem, ingen havde tænkt sig at
beholde.

**Browserkode bliver meldt som udefineret.** Et Node-script, der giver
funktioner videre til en browser, får `no-undef`-fejl på `document` og `window`,
og nogen slår `no-undef` fra, hvilket også skjuler ægte tastefejl. Erklær hvert
miljø, koden faktisk kører i, gennem `languageOptions.globals` for de filer, der
kører der.

**En egen regel lader alt passere.** En regel, hvis visitor peger på en
knudetype, der aldrig forekommer, eller hvis betingelse er vendt om, melder
simpelthen aldrig noget, og tavshed ligner overholdelse til forveksling. Test
hver egen regel med ESLints `RuleTester` med kode, der skal bestå, og kode, der
skal fejle, så en regel, der holder op med at melde, falder i sin egen test, før
den svigter kodebasen.

## Læs mere

- [Core Concepts](https://eslint.org/docs/latest/use/core-concepts/) — regler,
  rettelser, plugins, parsere og processorer, som projektet selv definerer dem.
- [Configuration Files](https://eslint.org/docs/latest/use/configure/configuration-files)
  — flat config-arrayet, filmønstre, globale ignoreringer og hvordan objekterne
  flettes sammen.
- [Configure Rules](https://eslint.org/docs/latest/use/configure/rules) —
  alvorsgrader, regelindstillinger og de kommentarer, der slår en regel fra for
  en enkelt linje.
- [Command Line Interface Reference](https://eslint.org/docs/latest/use/command-line-interface)
  — hvert flag, heriblandt `--max-warnings`, og hvad hver exitkode betyder.
- [ESLint v10.0.0 released](https://eslint.org/blog/2026/02/eslint-v10.0.0-released/)
  — udgivelsesnoterne om fjernelsen af eslintrc og den nye måde at finde
  konfigurationen på.
- [Custom Rules](https://eslint.org/docs/latest/extend/custom-rules) — at skrive
  en regel mod syntakstræet og bevise den med `RuleTester`.

<https://engineer.company/da/glossary/eslint/>
