Skip to content

Build1 publisher3 min readPublished

A Go type checker carries oxlint through Vue's 445 files in 0.9 seconds with type rules on

A dev.to benchmark clocks ESLint's type-aware pass on Vue's core at 12 seconds and oxlint's at 0.9. The speed comes from tsgolint, an experimental Go type checker that ships behind a flag and is not tsc.

The Engineer · Build desk

What happened

  • A dev.to writer cloned Vue's core repository, 445 TypeScript files and about 150,000 lines, and linted the tree four ways in a clean Node 20 container, taking wall-clock medians of repeated runs.
  • On the plain recommended rules, ESLint 9 with typescript-eslint took 4.4 seconds and oxlint took 0.24, about eighteen times faster.
  • The type-aware mode sits behind a flag, requires the separate oxlint-tsgolint package, and is labelled experimental by oxlint itself.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • capability At 75 milliseconds of engine time the syntactic pass fits inside an on-save budget, which the author argues means linting on every keystroke instead of waiting for a CI job to report.
  • decision Teams already running recommendedTypeChecked in CI now choose between 12 seconds of tsc-backed findings and 0.9 seconds from a separate Go implementation of the same type rules.
  • constraint Because the default rule lists differ and oxlint may lack an ESLint-only plugin, replacing the ESLint job requires a rule-by-rule audit first.
  • cost The 0.9-second figure comes with an extra experimental dependency to install and track, and whoever owns the CI pipeline carries that maintenance.

The 75 milliseconds is the only figure in the set that measures linting. oxlint prints its own engine time at the end of a run, and on Vue's core that was 75 ms against a 0.24-second wall clock [5]. The difference, about 0.165 seconds or 69 percent of what the shell reported, was Node starting and npx resolving the binary [1]. Across 150,000 lines, that engine time works out to roughly two million lines a second [2]. A pre-commit hook pays the process spawn on every invocation, so 0.24 seconds is what a hook costs; an editor extension holding a resident process would see the 75 ms.

The expensive rules are the type-aware ones. `no-floating-promises`, `no-misused-promises` and `await-thenable` all need the checker to know what a value actually is [7]. Switching to `recommendedTypeChecked` took ESLint from 4.4 seconds to 12, and the post attributes that to having to build a TypeScript program before it can lint a line [3][8]. The added cost is 7.6 seconds [3]. oxlint's type-aware run added 0.66 seconds over its own default [4], and the flag moved its rule count from 96 to 111, fifteen more rules [9][5].

The benchmark ran a VoidZero tool against the codebase of the framework whose author started VoidZero: oxlint is written in Rust and Evan You founded the company after Vue and Vite [14]. Its author expected to find the tool fast but limited. "The limited part did not survive the test," the author wrote [15].

Two conditions sit under the thirteenfold gap on the type-aware pass [4]. The rule lists are not the same; the post says the two default sets overlap heavily but are not identical, and that typescript-eslint's counts are its own [9]. And the type checker underneath is not tsc. tsgolint is a Go-based TypeScript type checker, and per the post the reason it is fast is that it is not the official compiler [13].

So the type-aware comparison times two different implementations of the same class of rules. The post reports wall-clock medians of repeated runs in a clean Node 20 container [1]; it does not report whether the two type-aware runs flagged the same code [6]. For a team that currently trusts `recommendedTypeChecked` output in CI, agreement is the thing to establish before the ESLint job is deleted, and the post says as much: test it against your own code [13].

Adoption takes a few steps. Run `--type-aware` without its companion package and it fails cleanly with the install instruction [12]. The flag pulls in the separate `oxlint-tsgolint` package, and oxlint itself labels the type-checking part experimental [11].

In my view the syntactic mode is fast enough for a hook now: 96 rules, 0.24 seconds, no new type checker in the dependency graph [2][9]. If a project needs one specific ESLint rule or a plugin that exists only for ESLint, oxlint may not have it, and the post is blunt that no speed number rescues a missing rule [10]. The type-aware mode I would run alongside typescript-eslint on the same tree and compare findings first, because tsgolint is a different implementation of the type rules [13].

What to watch

  • Whether oxlint promotes --type-aware out of experimental and folds oxlint-tsgolint into the default install.
  • A published diff of findings between typescript-eslint's recommendedTypeChecked and tsgolint on the same tree.
  • The same four-way run on a repository whose TypeScript program is far larger than Vue's 150,000 lines.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories