12k
All articles

TypeScript mit ESLint linten

ESLint 10 Flat Config für TypeScript: Setup mit typescript-eslint, typed linting per projectService und sauberes Prettier.

OpenReplay Team
OpenReplay Team
TypeScript mit ESLint linten

Stand Juli 2026 ist der aktuelle Weg, TypeScript zu linten, ESLint 10 mit dem Paket typescript-eslint in der Flat Config (eslint.config.mjs) – nicht das alte .eslintrc-Setup, das in den meisten Suchergebnissen immer noch auftaucht.

Falls Sie schon einmal eine Konfiguration aus einem Tutorial von 2022 eingefügt haben und mit ansehen mussten, wie ESLint sie komplett ignoriert: Das ist der Grund. Sie wurde für ein Konfigurationssystem geschrieben, das es nicht mehr gibt. Der Ersatz ist kurz, allerdings benötigt der typbewusste Teil eine zusätzliche Option, die man leicht übersieht.

ESLint 10 hat das eslintrc-Konfigurationssystem vollständig entfernt, wie es das Projekt in seinen Plänen zur Einführung der Flat Config bereits angekündigt hatte. Diese eine Änderung macht praktisch jedes Tutorial von vor 2024 unbrauchbar, denn ESLint liest .eslintrc- oder .eslintignore-Dateien überhaupt nicht mehr ein. Dieser Leitfaden liefert Ihnen eine korrekte, direkt kopierbare Flat Config für TypeScript, zeigt, wie Sie typbewusste Regeln aktivieren, und bindet das Linting in Ihre Scripts, Ihren Editor und Ihre CI ein.

Wichtigste Erkenntnisse

  • Der moderne Stack besteht aus ESLint 10 plus typescript-eslint v8 in der Flat Config; .eslintrc/.eslintignore sind mit ESLint 10 endgültig Geschichte.
  • Eine minimale Konfiguration übergibt js.configs.recommended und tseslint.configs.recommended an defineConfig() aus eslint/config, in einer Datei namens eslint.config.js/.mjs.
  • Typbewusste Regeln wie no-floating-promises benötigen parserOptions: { projectService: true }. Ein leeres parserOptions aktiviert sie nicht.
  • Typed Linting verlangt von TypeScript, Ihr Projekt vor dem Linten zu bauen, ist also langsamer; führen Sie es in der CI aus und verlassen Sie sich im Editor auf das IDE-Caching.
  • In der Flat Config ist das --ext-Flag überflüssig: Die Dateiauswahl steckt im files-Glob des jeweiligen Blocks, das Lint-Script lautet also schlicht eslint ..

Erledigen ESLint und TypeScript dieselbe Aufgabe?

ESLint und TypeScript ergänzen einander, sie konkurrieren nicht. Einige wenige typescript-eslint-Regeln greifen zwar auf TypeScripts Type Checker zu, um Ihren Code tiefer zu analysieren, doch die beiden Werkzeuge beantworten unterschiedliche Fragen: Der TypeScript-Compiler prüft, ob die Typen zusammenpassen, während ESLint Stilvorgaben durchsetzt und wahrscheinliche Fehler aufspürt (ungenutzte Variablen, floating Promises, unsichere Muster) – und zwar über die gesamte Codebase hinweg. Sie setzen beides ein.

Falls Sie von TSLint migrieren: Das Projekt ist seit Jahren tot. Seine Betreiber kündigten 2019 an, es zugunsten von typescript-eslint einzustellen, und das ESLint-Ökosystem wurde zum Standard für das Linten von TypeScript. Es gibt keinen Grund, in einem neuen Projekt zu TSLint zu greifen.

Eine Voraussetzung noch vor der Installation: ESLint 10 hat die Unterstützung älterer Node-Versionen eingestellt. Es läuft jetzt auf Node.js ab v20.19.0, ab v22.13.0 oder ab v24; v21.x und v23.x werden nicht mehr unterstützt.

Wie richtet man ESLint für TypeScript ein?

Installieren Sie die vier Pakete, die Sie tatsächlich brauchen:

npm i -D eslint @eslint/js typescript typescript-eslint

Das Hilfspaket typescript-eslint bündelt Parser und Plugin, sodass Sie @typescript-eslint/parser und @typescript-eslint/eslint-plugin nicht von Hand verdrahten müssen. Es unterstützt die aktuelle Major-Version: der dokumentierte ESLint-Versionsbereich von typescript-eslint umfasst ^8.57.0 || ^9.0.0 || ^10.0.0, sodass typescript-eslint@latest (v8.x) problemlos unter ESLint 10 läuft.

Legen Sie eslint.config.mjs an (Flat Config, nicht .eslintrc):

// eslint.config.mjs
import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint';

export default defineConfig(
  js.configs.recommended,
  tseslint.configs.recommended,
);

Das ist eine funktionsfähige Basis: die empfohlenen Kernregeln von ESLint plus das Recommended-Set von typescript-eslint, das Parser und Plugin von typescript-eslint gleich mit festlegt. defineConfig() stammt aus dem ESLint-Kern und ist der Helfer, zu dem man heute greifen sollte, denn typescript-eslint hat sein eigenes tseslint.config() zugunsten davon als deprecated markiert. Der alte Helfer funktioniert weiterhin, eine bereits laufende Konfiguration ist also nicht kaputt – neue Setups sollten aber defineConfig() verwenden. Importieren Sie tseslint in beiden Fällen weiterhin, da Sie es für tseslint.configs.* und die Glob-Helfer nach wie vor benötigen.

Strenger werden und dann einzelne Regeln feinjustieren

recommended ist der Ausgangspunkt; zwei optionale Presets legen die Latte höher. tseslint.configs.strict ergänzt meinungsstärkere Korrektheitsregeln, und tseslint.configs.stylistic fügt Konsistenzregeln hinzu, die keine Typinformationen benötigen. Fügen Sie sie neben recommended in das Konfigurations-Array ein.

Jede Regel lässt sich in einem rules-Block überschreiben. Es gibt drei Schweregrade: off (bzw. 0) schaltet die Regel vollständig ab, warn (bzw. 1) meldet das Problem, ohne den Exit-Code zu beeinflussen, und error (bzw. 2) meldet es und lässt ESLint mit Code 1 beenden. Verwenden Sie warn für Dinge, die sichtbar, aber nicht blockierend sein sollen; verwenden Sie error für alles, was nicht ins Repository gelangen darf, da es einen Exit-Code ungleich null erzeugt und die CI scheitern lässt.

rules: {
  '@typescript-eslint/no-explicit-any': 'warn',
  '@typescript-eslint/no-unused-vars': 'error',
}

Bevorzugen Sie in modernen Konfigurationen die String-Schweregrade ('warn'/'error') gegenüber der numerischen Form. Sie lesen sich klarer, und der rein numerische Stil ist ein typisches Merkmal veralteter .eslintrc-Tutorials.

Typbewusstes Linting: die Regeln, die Typinformationen benötigen

Einige der wertvollsten Regeln – darunter no-floating-promises und no-misused-promises – benötigen Typinformationen, und Sie aktivieren diese, indem Sie parserOptions: { projectService: true } hinzufügen. Das ist seit typescript-eslint v8 der empfohlene Weg, Typed Linting einzuschalten; es ersetzt die ältere project-Option, weil es weniger Konfiguration erfordert und schneller läuft. Stellen Sie außerdem Ihre Presets auf die typgeprüften Varianten um (recommendedTypeChecked, strictTypeChecked, stylisticTypeChecked). Ein leeres parserOptions: {} aktiviert typbewusstes Linting nicht – ein häufiger Fehler in kopierten Konfigurationen.

{
  files: ['**/*.ts', '**/*.tsx'],
  extends: [tseslint.configs.recommendedTypeChecked],
  languageOptions: {
    parserOptions: {
      projectService: true,
      tsconfigRootDir: import.meta.dirname,
    },
  },
}

Typed Linting hat einen realen Preis. Es einzuschalten bedeutet, dass TypeScript Ihr Projekt bauen muss, bevor ESLint es linten kann – in einer kleinen Codebase eine oder zwei Sekunden, in einer großen spürbar länger. Der Rat von typescript-eslint selbst stützt sich hier auf eine Asymmetrie: Editor-Plugins cachen Typinformationen und entgehen dem Aufwand weitgehend. Führen Sie das vollständige typgeprüfte Linting also in der CI und im Pre-Commit-Hook aus und lassen Sie sich im Alltag vom Editor absichern. projectService beseitigt außerdem den alten Workaround, eine separate tsconfig.eslint.json zu pflegen, da es dasselbe Projekt nutzt wie der Editor.

JS von TS trennen und Ignores festlegen

Typgeprüfte Regeln ergeben nur bei Dateien Sinn, die TypeScript versteht. Beschränken Sie sie daher auf **/*.ts/**/*.tsx und schalten Sie sie für reines JavaScript ab. typescript-eslint liefert genau dafür ein Preset mit. Die eigene Dokumentation wendet tseslint.configs.disableTypeChecked auf einen **/*.js-Block an, um das TypeScript-spezifische Setup wieder zu entfernen. In der Flat Config sind Ignores schlicht ein Konfigurationsblock, der nur einen ignores-Schlüssel enthält – das ist der Ersatz für .eslintignore.

// eslint.config.mjs
import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint';
import prettier from 'eslint-config-prettier';

export default defineConfig(
  { ignores: ['dist/', 'node_modules/', 'coverage/', '**/*.d.ts'] },
  js.configs.recommended,
  {
    files: ['**/*.ts', '**/*.tsx'],
    extends: [tseslint.configs.recommendedTypeChecked],
    languageOptions: {
      parserOptions: { projectService: true, tsconfigRootDir: import.meta.dirname },
    },
    rules: { '@typescript-eslint/no-explicit-any': 'warn' },
  },
  { files: ['**/*.js', '**/*.mjs'], extends: [tseslint.configs.disableTypeChecked] },
  prettier, // must be last
);

Formatierung Prettier überlassen und dann den Workflow verdrahten

Halten Sie die Formatierung aus ESLint heraus. Fügen Sie eslint-config-prettier als Letztes hinzu, um die stilistischen ESLint-Regeln abzuschalten, die mit Prettier in Konflikt geraten würden, und pinnen Sie es auf ^10.1.8 oder neuer. Diese Version ist wichtig: Im Juli 2025 führte ein Phishing-Angriff auf die npm-Zugangsdaten eines Maintainers zu vier manipulierten Releases, erfasst als CVE-2025-54313. Die Versionen 8.10.1, 9.1.1, 10.1.6 und 10.1.7 enthielten ein postinstall-Script, das auf Windows-Rechnern eine mitgelieferte DLL-Payload ausführte; die bereinigten Releases sind 8.10.2, 9.1.2 und 10.1.8. Betroffen waren ausschließlich diese vier Versionen, und die Payload lief nur unter Windows, sodass saubere ältere Builds wie 10.1.5 zu keinem Zeitpunkt kompromittiert waren. Prettier über eslint-plugin-prettier als ESLint-Regel auszuführen, ist möglich, aber optional; viele Teams verzichten darauf, weil es das Linting langsamer und lauter macht.

Fügen Sie ein Lint-Script hinzu. Ein --ext-Flag ist nicht nötig, da die Dateiauswahl im files-Glob des jeweiligen Konfigurationsblocks steckt:

{
  "scripts": {
    "lint": "eslint .",
    "lint:fix": "eslint . --fix"
  }
}

Von dort aus führen Sie eslint --fix mit Husky und lint-staged vor jedem Commit auf den gestagten Dateien aus, aktivieren in VS Code das Fix-on-Save über "source.fixAll.eslint": "explicit" in codeActionsOnSave und lassen eslint . als CI-Schritt laufen, damit eine fehlschlagende Regel den Merge blockiert.

Eine letzte Sache, bei der Handlungsbedarf besteht: ESLint 9 hat am 06.08.2026 sein End of Life erreicht und erhält keine weiteren Updates. Falls Sie noch auf ESLint 9 sind: Die obige Konfiguration funktioniert unverändert unter ESLint 10, aktualisieren Sie also die Laufzeitumgebung und machen Sie weiter. Beginnen Sie mit der minimalen zweizeiligen Konfiguration, ergänzen Sie recommendedTypeChecked mit projectService, sobald Sie die Promise-Sicherheitsregeln möchten, und setzen Sie eslint-config-prettier an letzte Stelle.

FAQs

Sollte ich typbewusstes Linting aktivieren, und was kostet es?

Aktivieren Sie es, wenn Sie die besonders wertvollen Korrektheitsregeln wie no-floating-promises und no-misused-promises nutzen möchten, die ohne Typinformationen nicht funktionieren können. Der Preis besteht darin, dass ESLint TypeScript auffordert, Ihr Projekt vor dem Linten zu bauen – bei kleinen Projekten vernachlässigbar, bei großen spürbar. Die meisten Teams führen das vollständige typgeprüfte Linting in der CI und im Pre-Commit-Hook aus und verlassen sich im Editor auf das IDE-Caching, wo der Mehraufwand entfällt.

Was ist der Unterschied zwischen projectService und project beim Typed Linting?

Beide aktivieren Typed Linting, aber projectService ist das, was typescript-eslint seit v8 empfiehlt, weil es einfacher zu konfigurieren ist und schneller lintet: Es verwendet dieselbe tsconfig.json wieder, die auch Ihr Editor bereits nutzt. Die ältere project-Option verlangt, dass Sie eine oder mehrere TSConfig-Dateien per Pfad angeben, und zwang Teams häufig dazu, eine separate tsconfig.eslint.json zu pflegen. Verwenden Sie projectService: true, sofern Sie keinen konkreten Grund dagegen haben.

Funktioniert das --ext-Flag in der ESLint Flat Config noch?

Nein, --ext wird in der Flat Config nicht mehr benötigt. Die Dateiauswahl steckt im files-Glob des jeweiligen Konfigurationsblocks, zum Beispiel files: ['**/*.ts', '**/*.tsx'], sodass ESLint bereits weiß, welche Dateien zu linten sind. Ihr Lint-Script lautet dann einfach eslint . ohne Erweiterungs-Flag. Scripts, die weiterhin --ext übergeben, stammen aus Tutorials von vor der Flat Config, die für das entfernte eslintrc-System geschrieben wurden.

Sollte ich eslint-config-prettier oder eslint-plugin-prettier verwenden?

Verwenden Sie für die meisten Projekte eslint-config-prettier. Es schaltet die stilistischen ESLint-Regeln ab, die mit Prettier kollidieren, und verursacht keinen Laufzeit-Overhead; platzieren Sie es als Letztes in Ihrem Konfigurations-Array. Der Ansatz mit eslint-plugin-prettier führt Prettier als echte Lint-Regel aus, was optional und langsamer ist und jede Formatierungsabweichung als Lint-Fehler meldet. Pinnen Sie eslint-config-prettier auf 10.1.8 oder neuer, um dem Supply-Chain-Vorfall vom Juli 2025 aus dem Weg zu gehen.

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.