ts-r-lint

Linter. Replaces ESLint + typescript-eslint.

  • Pre-alpha
  • Works from source

ts-r-lint runs ESLint-compatible rules over JavaScript and TypeScript. It reads the config you already have, reports in ESLint’s formats and exits with ESLint’s codes, so it can stand in for eslint in scripts and CI when your config only uses the rules it has.

Three projects with ESLint configs, totalShorter is faster. Pre-release build, real app.
  • ts-r-lint1,721 ms
  • ESLint14,725 ms

8.6× faster linting

What switching looks like

Nothing is on npm yet. Once it is, switching looks like this: ts-r-lint reads the config you already have, so the change is to the command, not the project.

package.json
  "scripts": {
-   "lint": "eslint .",
+   "lint": "ts-r-lint .",
-   "lint:fix": "eslint --fix .",
+   "lint:fix": "ts-r-lint --fix .",
  }

What works, and what doesn’t yet

Works today

  • 103 rules: all 64 of ESLint 10’s recommended set and typescript-eslint’s recommended and strict rules that don’t need types
  • Every case of the published ESLint and typescript-eslint tests for those rules matches
  • ESLint flat config, .oxlintrc.json and biome.json
  • --fix, eslint-disable comments and inline config, with unused-disable reports
  • Output as stylish, json, sarif or GitHub Actions annotations

Not yet

  • No type-aware rules; they are skipped and listed on stderr
  • No ESLint plugins other than typescript-eslint

Measured

Every run, on the same reference app as the home page, with the command and commit that recorded it.

ts-r-lint against ESLint and oxlint

Each project linted with its own config. Not like-for-like yet: ESLint also runs plugin rules ts-r-lint does not have (on TypeORM most of its problems come from jsdoc rules), and where ts-r-check's diagnostics differ from tsc's, ts-r-lint runs without type information (its parity gate), so its type-aware column is a type check plus the untyped rules. The rules themselves match ESLint's and typescript-eslint's test suites (see Correctness).

Three projects with ESLint configs, totalShorter is faster, in ms
  • ts-r
  • Other tools
  • ts-r-lint1,721 ms
  • ESLint14,725 ms
tRPC server and client sourcesShorter is faster, in ms
  • ts-r
  • Other tools
  • ts-r-lint, no type check20 ms
  • ts-r-lint186 ms
  • ESLint, type-aware2,566 ms
TypeORM packages/typeorm/srcShorter is faster, in ms
  • ts-r
  • Other tools
  • ts-r-lint, no type check194 ms
  • ts-r-lint810 ms
  • ESLint, type-aware6,718 ms
More projects, and memory
RunTimePeak memory
Playwright core sources: ts-r-lint / no type check725 / 59 ms465 / 17 MB
Playwright core sources: ESLint5,441 ms2,341 MB
date-fns pkgs/core/src: ts-r-lint76 ms14 MB
date-fns pkgs/core/src: oxlint (its own config)348 ms301 MB
tRPC: ts-r-lint / ESLint186 / 2,566 ms148 / 992 MB
TypeORM: ts-r-lint / ESLint810 / 6,718 ms380 / 1,748 MB
How we measured
Measured
Wall time of the whole command with hyperfine (cargo xtask bench --repos), median of 3 to 5 runs; peak RSS of one extra run
Machine
Apple M-series MacBook (macOS arm64, 16 cores, 48 GB), shared with other jobs while measuring; release build, 4 threads
Software
ts-r-lint release build with 4 threads; each repo's own ESLint or oxlint from its lockfile
Input
tRPC, TypeORM, Playwright and date-fns at the commits pinned in bench/repos.toml, with their own lint configs
Command
cargo xtask bench --fetch-repos --repos trpc,typeorm,playwright,date-fns && cargo xtask bench --repos trpc,typeorm,playwright,date-fns --memory lint-
Recorded in
commit 9c3a371

Correctness

Compared with the tool ts-r-lint replaces, on its own tests and on real code.

  • Lint rules100%

    8,597 of 8,597 cases match

    Every case of the published ESLint and typescript-eslint tests for the 103 rules. Commit 27c280e.

Command line

An excerpt of ts-r-lint --help. You can also run it through the launcher as ts-r lint.

Next to ESLint

A common split: run ts-r-lint on every save or commit for the fast rules, and keep ESLint in CI for type-aware rules and plugins ts-r-lint doesn’t have yet. In the editor, ts-r-lsp shows the same diagnostics.

ts-r-lint --help
ts-r-lint [options] [paths...]

  -f, --format <name>      stylish (default), json, sarif, github
  -c, --config <path>      Use this config for every file
      --fix                Apply fixes
      --max-warnings <n>   Exit 1 above this many warnings
      --list-rules         Print the rules ts-r-lint has