mrkeyoor.com_
Thu 06 Aug 01:03 UTC
npmCLI & Toolingupdated 05 Aug 2026

typescript-eslint

typescript-eslint is the tooling that makes ESLint understand TypeScript. The umbrella package bundles the parser (which turns TS into an AST ESLint can read), the plugin with over 100 TypeScript-specific rules, and helper functions for flat config. Its signature feature is type-aware linting: rules like no-floating-promises and no-unsafe-assignment ask the actual TypeScript type checker questions, catching bug classes that neither plain ESLint nor tsc reports. If ESLint runs on a .ts file anywhere, this project is in the middle of it, and since v8 the tseslint.config helper is the standard way to wire it up.

Verdict

Mandatory infrastructure for linting TypeScript with ESLint, and the type-aware rules alone justify the setup cost on production codebases. On big repos, pair it with a fast Rust linter for quick feedback and accept that the type-checked run lives in CI.

API stability4/5v8 has been current since mid-2024 with weekly minor releases that stay semver-clean; majors land roughly yearly and mostly reshuffle preset contents and deprecations, which shows up as new lint errors rather than API breaks.
Docs5/5typescript-eslint.io documents every rule with examples, has honest performance and troubleshooting guides, a typed-linting FAQ, and a playground that reproduces rule behavior in the browser.
Maintenance4/5Very active team with a push on August 5, 2026 and a steady weekly release cadence, funded through Open Collective and sponsorships rather than a company; 270 open issues and PRs on a huge surface is well managed.
Ecosystem5/5About 88M weekly downloads for the umbrella package alone, every TS framework config (Next, Nuxt, Astro, Expo) builds on the parser and plugin, and shared configs across the ecosystem assume it.

Use it if

  • You run ESLint on any TypeScript codebase; there is no serious alternative for making core ESLint parse TS at all
  • You want type-aware rules like no-floating-promises, await-thenable, and no-misused-promises that catch async bugs tsc happily compiles
  • You need to layer style and correctness presets (recommended, strict, stylistic, and their type-checked variants) and adjust individual rules per project
  • You write custom lint rules for your team and need the typed AST utilities that @typescript-eslint/utils provides
Skip it if

Setup reality

npm install with eslint and typescript as peers, then flat config with tseslint.config gets basic linting in five lines. The pain starts when you enable type-checked presets: you must set parserOptions.projectService (or project) plus tsconfigRootDir, and any file ESLint sees that is not covered by a tsconfig throws a parsing error, which bites config files, scripts, and generated code until you add allowDefaultProject or a disableTypeChecked block. Monorepos multiply this per package. Expect type-aware runs to be several times slower than plain linting since the TypeScript checker does real work, and remember eslint 8.57+, 9, or 10 plus typescript below 6.1 are the supported peers.

Patterns

Minimal flat config for TypeScriptflat-config-quickstart

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

export default tseslint.config(
  eslint.configs.recommended,
  tseslint.configs.recommended,
);
// run: npx eslint .

tseslint.config() gives typed autocomplete and flattens nested arrays; the recommended preset does not need type information.

Turn on type-aware lintingenable-type-checking

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  eslint.configs.recommended,
  tseslint.configs.recommendedTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
);

projectService finds the right tsconfig per file automatically; without tsconfigRootDir, editors and CLI can resolve projects differently.

Keep type-checked rules off JS filesexclude-js-from-type-check

export default tseslint.config(
  tseslint.configs.recommendedTypeChecked,
  {
    files: ['**/*.js', '**/*.mjs'],
    extends: [tseslint.configs.disableTypeChecked],
  },
);

Without this block, plain JS config files hit "was not found by the project service" parsing errors the first time you lint.

Lint scripts not covered by tsconfiglint-files-outside-tsconfig

export default tseslint.config(
  tseslint.configs.recommendedTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        projectService: {
          allowDefaultProject: ['*.config.ts', 'scripts/*.ts'],
        },
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
);

allowDefaultProject takes glob patterns relative to the root; keep the list short because default-project files lint noticeably slower.

Adjust a single rule's optionscustomize-rule

export default tseslint.config(
  tseslint.configs.recommended,
  {
    rules: {
      '@typescript-eslint/no-unused-vars': [
        'error',
        { argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
      ],
    },
  },
);

The preset already turns this rule on; your object replaces its options entirely rather than merging with the defaults.

Opt into the strict and stylistic presetsstrict-and-stylistic

export default tseslint.config(
  eslint.configs.recommended,
  tseslint.configs.strictTypeChecked,
  tseslint.configs.stylisticTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
);

strictTypeChecked is a superset of recommendedTypeChecked and the team allows it to change more between minors; pin versions if that bothers you.

Catch unawaited promisescatch-floating-promises

// rule: @typescript-eslint/no-floating-promises (type-checked presets)
async function save() { /* ... */ }

save();        // lint error: floating promise
void save();   // explicit fire-and-forget passes
await save();  // passes

This is the single highest-value type-aware rule; it needs projectService configured or it errors out asking for type information.

Ban specific types with custom messagesban-with-message

rules: {
  '@typescript-eslint/no-restricted-types': [
    'error',
    {
      types: {
        Object: { message: 'Use object or a specific shape instead.' },
        String: { message: 'Use string (lowercase) instead.', fixWith: 'string' },
      },
    },
  ],
}

v8 split the old ban-types rule; no-restricted-types handles your custom bans while no-wrapper-object-types covers the classic built-in offenders.

Enforce type-only importsenforce-consistent-imports

rules: {
  '@typescript-eslint/consistent-type-imports': [
    'error',
    { prefer: 'type-imports', fixStyle: 'inline-type-imports' },
  ],
}

Auto-fix rewrites imports to import type or inline type modifiers, which keeps bundlers and isolatedModules happy about erasable imports.

Disable a rule for one line with a reasondisable-rule-inline

// eslint-disable-next-line @typescript-eslint/no-explicit-any -- third-party API returns untyped JSON
const payload: any = await legacyClient.fetch();

The -- description is enforceable via the eslint-comments plugin; naked disables are how any leaks back into a strict codebase.

Enforce naming conventionsnaming-convention

rules: {
  '@typescript-eslint/naming-convention': [
    'error',
    { selector: 'interface', format: ['PascalCase'] },
    { selector: 'typeParameter', format: ['PascalCase'], prefix: ['T'] },
    { selector: 'variable', modifiers: ['const'], format: ['camelCase', 'UPPER_CASE'] },
  ],
}

Selectors are evaluated in order and the first match wins, so put specific selectors before general ones or they never apply.

Scope linting to source directorieslimit-linted-files

export default tseslint.config(
  {
    ignores: ['dist/**', 'coverage/**', '**/*.generated.ts'],
  },
  tseslint.configs.recommendedTypeChecked,
  // ...
);

A config object containing only ignores acts as global ignores in flat config; linting build output is the classic cause of mysterious slowness.

Alternatives

PackageRegistryPick it when
@biomejs/biomenpmYou want linting plus formatting in one fast Rust tool and can live without type-aware rules and the ESLint plugin ecosystem
oxlintnpmYou want a very fast first-pass linter, including as a preflight before a slower typescript-eslint run in CI
eslintnpmYour codebase is plain JavaScript, where core ESLint alone covers you without any of this