Skip to content

Commit ec454e0

Browse files
Boshenclaudecamc314camchenry
authored
Type-Aware Linting Alpha (#625)
--------- Signed-off-by: Cam McHenry <camchenry@users.noreply.github.com> Signed-off-by: Cameron <cameron.clark@hey.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Cameron Clark <cameron.clark@hey.com> Co-authored-by: Cam McHenry <camchenry@users.noreply.github.com>
1 parent fa0d607 commit ec454e0

File tree

6 files changed

+274
-12
lines changed

6 files changed

+274
-12
lines changed

.vitepress/config/en.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const enConfig = defineLocaleConfig("root", {
2323
{
2424
text: "Resources",
2525
items: [
26-
{ text: "Blog", link: "/blog/2025-12-01-oxfmt-alpha" },
26+
{ text: "Blog", link: "/blog/2025-12-08-oxfmt-alpha" },
2727
{ text: "Team", link: "/team" },
2828
{ text: "Release Notes", link: "https://github.com/oxc-project/oxc/releases" },
2929
{ text: "Branding", link: "/branding" },

.vitepress/config/inlined-scripts/banner.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
}
77
};
88

9-
window.__OXC_BANNER_ID__ = "/blog/2025-12-01-oxfmt-alpha";
9+
window.__OXC_BANNER_ID__ = "/blog/2025-12-08-type-aware-alpha";
1010
restore(`oxc-banner-dismissed-${__OXC_BANNER_ID__}`, "banner-dismissed");
1111
})();

.vitepress/sidebar.blog.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[
22
{
3-
"text": "Oxfmt Alpha",
4-
"link": "/blog/2025-12-01-oxfmt-alpha"
3+
"text": "Type-Aware Linting Alpha",
4+
"link": "/blog/2025-12-08-type-aware-alpha"
55
},
66
{
77
"text": "Oxlint JS Plugins Preview",

.vitepress/theme/components/Banner.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const hide = () => {
1717
};
1818
1919
// Sync with inlined-scripts/banner.js
20-
const slug = "/blog/2025-12-01-oxfmt-alpha";
20+
const slug = "/blog/2025-12-08-type-aware-alpha";
2121
2222
const bannerDismissed = useLocalStorage<boolean>(`oxc-banner-dismissed-${slug}`, false);
2323
@@ -46,7 +46,7 @@ const dismiss = () => {
4646

4747
<template>
4848
<div ref="el" class="banner banner-dismissed">
49-
<div class="text"><a :href="slug">Oxfmt: Announcing Oxc Formatter Alpha</a> 🎉</div>
49+
<div class="text"><a :href="slug">Announcing Type-Aware Linting Alpha</a> 🎉</div>
5050

5151
<button type="button" @click="dismiss">
5252
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
---
2+
title: Type-Aware Linting Alpha
3+
outline: deep
4+
authors:
5+
- cameron
6+
- camchenry
7+
---
8+
9+
<AppBlogPostHeader />
10+
11+
<br>
12+
13+
We're excited to announce the alpha release of type-aware linting in Oxlint!
14+
15+
## Overview
16+
17+
Following our [technical preview in August](/blog/2025-08-17-oxlint-type-aware), we're excited to announce that type-aware linting has reached alpha status. This milestone brings significant improvements in stability, configurability, and rule coverage.
18+
19+
Type-aware linting enables powerful rules like `no-floating-promises`, `no-misused-promises`, and `await-thenable` that catch bugs by utilizing TypeScript's type system. With 43 type-aware rules now available, you can catch entire categories of runtime errors before they happen.
20+
21+
**In this post:**
22+
23+
- [Quick Start](#quick-start) - Get started with type-aware linting in minutes
24+
- [Performance](#performance) - See how much faster type-aware linting is compared to ESLint
25+
- [What's new since the technical preview](#what-s-new-since-the-technical-preview) - New features and improvements
26+
- [Technical details](#technical-details) - How type-aware linting works under the hood
27+
- [What's next](#what-s-next) - Upcoming improvements for the beta release
28+
29+
## Quick Start
30+
31+
Install `oxlint` and `oxlint-tsgolint`, then run with the `--type-aware` flag:
32+
33+
::: code-group
34+
35+
```sh [npm]
36+
npm add -D oxlint oxlint-tsgolint@latest
37+
npx oxlint --type-aware
38+
```
39+
40+
```sh [pnpm]
41+
pnpm add -D oxlint oxlint-tsgolint@latest
42+
pnpm oxlint --type-aware
43+
```
44+
45+
```sh [yarn]
46+
yarn add -D oxlint oxlint-tsgolint@latest
47+
yarn oxlint --type-aware
48+
```
49+
50+
```sh [bun]
51+
bun add -D oxlint oxlint-tsgolint@latest
52+
bunx oxlint --type-aware
53+
```
54+
55+
:::
56+
57+
To try a specific type-aware rule without other configuration (`oxlint-tsgolint` must be installed globally or locally already):
58+
59+
::: code-group
60+
61+
```sh [npm]
62+
npx oxlint --type-aware -A all -D typescript/no-floating-promises
63+
```
64+
65+
```sh [pnpm]
66+
pnpx oxlint --type-aware -A all -D typescript/no-floating-promises
67+
```
68+
69+
```sh [yarn]
70+
yarn oxlint --type-aware -A all -D typescript/no-floating-promises
71+
```
72+
73+
```sh [bun]
74+
bunx oxlint --type-aware -A all -D typescript/no-floating-promises
75+
```
76+
77+
:::
78+
79+
For more configuration options, see our [usage guide](/docs/guide/usage/linter/type-aware).
80+
81+
## Performance
82+
83+
| Project | Oxlint + Type Aware | ESLint + typescript-eslint | Improvement |
84+
| --------------- | ------------------- | -------------------------- | ----------- |
85+
| vuejs/core | 2.531 s | 20.800 s | 8.22x |
86+
| outline/outline | 4.448 s | 55.070 s | 12.38x |
87+
88+
Benchmarks were performed on a MacBook Pro M2 Max 12 Cores (8 performance and 4 efficiency).
89+
90+
Our performance testing shows that `oxlint` with type-aware linting is around 10 times faster than `eslint` with `typescript-eslint`. Take a look at our [performance benchmarks](https://github.com/oxc-project/bench-linter) for more details.
91+
92+
Oxlint can also be used to typecheck your codebase while linting. This avoids a duplicate work, as much of the type information is already computed during type-aware linting.
93+
94+
:::warning Known Issues
95+
While `tsgolint` is ready for testing in production codebases, you may encounter issues with running out of memory when working with very large codebases. We are working on optimizing the memory usage for the next milestone. We would love if you tried `tsgolint` and reported any out-of-memory issues to us in the [`tsgolint` repository](https://github.com/oxc-project/tsgolint) and included some details about your project to help us improve memory usage.
96+
:::
97+
98+
## What's new since the technical preview?
99+
100+
### Support for type-checking while linting
101+
102+
`tsgolint` now supports emitting type checking errors from TypeScript while linting. Since type-aware rules already require checking all of the types within a file, we are able to use this existing type information rather than discarding it. This means that in some cases, it is possible to skip doing a separate type-check command altogether (e.g., `tsc --noEmit`), reducing total time spent doing linting and type-checking in CI.
103+
104+
This is an experimental feature, but you can enable it by adding the `--type-check` and `--type-aware` flag to the `oxlint` command:
105+
106+
```
107+
$ oxlint --type-aware --type-check
108+
109+
× typescript(TS2322): Type 'number' is not assignable to type 'string'.
110+
╭─[index.ts:1:7]
111+
1 │ const message: string = 1
112+
· ───────
113+
╰────
114+
```
115+
116+
### Rule configuration support in `oxlint`
117+
118+
Type-aware rules that run in `tsgolint` can be configured in `oxlint` just like any other lint rule. For example, you can configure the `no-floating-promises` rule to allow certain safe calls or ignore `void`:
119+
120+
```json
121+
{
122+
"rules": {
123+
"typescript/no-floating-promises": [
124+
"error",
125+
{
126+
"ignoreVoid": true,
127+
"allowForKnownSafePromises": [
128+
{ "from": "file", "name": "SafePromise" },
129+
{ "from": "lib", "name": "PromiseLike" }
130+
]
131+
}
132+
]
133+
}
134+
}
135+
```
136+
137+
The configuration options are aligned with what `typescript-eslint` supports and documentation can be found in the configuration section for each rule (like [`no-floating-promises`](https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html#configuration)).
138+
139+
### Inline disable comment support in `oxlint`
140+
141+
Rules that run in `tsgolint` can now be disabled similar to any other `oxlint` rule by placing a comment in the file or on a line:
142+
143+
```ts
144+
/* oxlint-disable typescript/no-floating-promises */
145+
146+
// oxlint-disable-next-line typescript/no-floating-promises
147+
[1, 2, 3].map(async (x) => x + 1);
148+
```
149+
150+
### More supported rules
151+
152+
We've continued to make progress on porting popular rules from `typescript-eslint` which you can now use via `oxlint`. `tsgolint`, combined with `oxlint`, currently supports 43 type-aware rules.
153+
154+
Since the initial preview, support for the following rules has also been added:
155+
156+
- [`no-deprecated`](/docs/guide/usage/linter/rules/typescript/no-deprecated) (one of the most commonly requested rules)
157+
- [`prefer-includes`](/docs/guide/usage/linter/rules/typescript/prefer-includes)
158+
- [`strict-boolean-expressions`](/docs/guide/usage/linter/rules/typescript/strict-boolean-expressions)
159+
160+
### TypeScript program diagnostics are now reported
161+
162+
Previously, if TypeScript failed to create and parse a program, these errors were not reported which led to confusion around why linting was not working. Now, we report any issues with creating a program as a diagnostic, including configuration issues in `tsconfig.json` files.
163+
164+
For example, if a `tsconfig.json` file contains `baseUrl`, that will be reported as an error, since `baseUrl` has been removed from TypeScript in v7.0:
165+
166+
```
167+
$ oxlint --type-aware
168+
169+
× typescript(tsconfig-error): Invalid tsconfig
170+
╭─[tsconfig.json:4:3]
171+
3 │ "compilerOptions": {
172+
4 │ "baseUrl": ".",
173+
· ─────────
174+
5 │ "experimentalDecorators": true,
175+
╰────
176+
help: Option 'baseUrl' has been removed. Please remove it from your configuration.
177+
See https://github.com/oxc-project/tsgolint/issues/351 for more information.
178+
```
179+
180+
### Automatic fixes for type-aware rules
181+
182+
Type-aware rules now support automatic fixes via the `--fix` flag. When you run `oxlint --type-aware --fix`, fixable diagnostics from `tsgolint` are applied just like regular `oxlint` fixes. This brings full parity with non-type-aware rules for the fix workflow.
183+
184+
## Technical details
185+
186+
### Architecture
187+
188+
Type-aware linting in Oxlint uses a unique two-binary architecture:
189+
190+
```
191+
oxlint CLI (Rust)
192+
├─ Handles file traversal, ignore logic, and diagnostics
193+
├─ Runs non-type-aware rules and custom JS plugins
194+
├─ Passes paths and configuration to tsgolint
195+
└─ Formats and displays results
196+
197+
tsgolint (Go)
198+
├─ Uses typescript-go directly for type checking
199+
├─ Executes type-aware rules
200+
└─ Returns structured diagnostics
201+
```
202+
203+
This design keeps Oxlint's core fast while leveraging TypeScript's type system through typescript-go. The frontend-backend separation means `oxlint` controls the user experience while `tsgolint` handles the heavy lifting of type analysis.
204+
205+
### TypeScript compatibility
206+
207+
`tsgolint` is based on [typescript-go](https://github.com/microsoft/typescript-go), Microsoft's Go-based rewrite that will become TypeScript v7.0. For more details on TypeScript 7's progress, see the [official TypeScript blog post](https://devblogs.microsoft.com/typescript/progress-on-typescript-7-december-2025/). This means that you might encounter some features which are no longer supported.
208+
209+
**Important compatibility notes:**
210+
211+
- Only TypeScript 7.0+ features are supported
212+
- Pre-7.0 syntax and deprecated features are not supported
213+
- Legacy `tsconfig.json` options like `baseUrl` have been removed in TypeScript 7.0
214+
215+
If you're using deprecated features from TypeScript 6.0 or earlier, you'll need to migrate your codebase first. See the [TypeScript migration guide](https://github.com/microsoft/TypeScript/issues/62508#issuecomment-3348649259) for help updating deprecated tsconfig options.
216+
217+
### Implementation details
218+
219+
`tsgolint` doesn't use typescript-go's public APIs. Instead, it compiles typescript-go by [shimming](https://github.com/oxc-project/tsgolint/tree/main/shim) internal APIs to make them accessible. We actively track typescript-go updates and fix breaking changes as needed.
220+
221+
Our typescript-go fork is synced regularly using renovatebot, ensuring we stay current with the latest improvements and fixes. Once TypeScript 7.0 is officially released, we will track stable releases rather than the tip of the main branch.
222+
223+
## What's next
224+
225+
We're actively working on the following improvements for the beta release:
226+
227+
- **More supported rules** - Currently we support 43 out of the 59 type-aware rules from `typescript-eslint`. As we head towards a beta release, we plan to continue expanding rule coverage.
228+
- **Performance and memory usage improvements** - We're going to continue to optimize performance, especially for very large monorepos.
229+
230+
## Acknowledgements
231+
232+
We'd like to extend our gratitude to:
233+
234+
- The TypeScript team for creating `typescript-go`.
235+
- The `typescript-eslint` team for their heartwarming support.
236+
- [@auvred](https://github.com/auvred) for creating `tsgolint`.
237+
- [@camchenry](https://github.com/camchenry) for continued performance work, as well as implementing rule option support.
238+
239+
## Try it out
240+
241+
Ready to get started? Head to the [Quick Start](#quick-start) section above to install and run type-aware linting.
242+
243+
We'd love to hear your feedback on type-aware linting and are excited to see how it helps improve your development workflow.
244+
245+
Connect with us:
246+
247+
- **Discord**: Join our [community server](https://discord.gg/9uXCAwqQZW) for real-time discussions
248+
- **GitHub**: Share feedback on [GitHub Discussions](https://github.com/oxc-project/oxc/discussions)
249+
- **Issues**: Report `oxlint` bugs to [oxc](https://github.com/oxc-project/oxc/issues) and type-aware linting bugs to [tsgolint](https://github.com/oxc-project/tsgolint/issues).

src/docs/guide/usage/linter/type-aware.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,6 @@ Run `oxlint` with `--type-aware`
3030
oxlint --type-aware
3131
```
3232

33-
## Unsupported Features
34-
35-
The following issues will be addressed for the alpha version.
36-
37-
- Auto-fixes for type-aware rules only work in the VS Code extension, not in the CLI (`oxlint --fix`)
38-
3933
## Unimplemented Rules
4034

4135
See https://github.com/oxc-project/tsgolint/issues/104
@@ -99,3 +93,22 @@ tsgolint is based on [typescript-go](https://github.com/microsoft/typescript-go)
9993
- If you're using deprecated features that were deprecated in TypeScript 6.0 or removed in TypeScript 7.0, you'll need to migrate your codebase first
10094

10195
For help migrating deprecated tsconfig options, see the [TypeScript migration guide](https://github.com/microsoft/TypeScript/issues/62508#issuecomment-3348649259).
96+
97+
## Architecture
98+
99+
Type-aware linting in Oxlint uses a unique two-binary architecture:
100+
101+
```
102+
oxlint CLI (Rust)
103+
├─ Handles file traversal, ignore logic, and diagnostics
104+
├─ Runs non-type-aware rules and custom JS plugins
105+
├─ Passes paths and configuration to tsgolint
106+
└─ Formats and displays results
107+
108+
tsgolint (Go)
109+
├─ Uses typescript-go directly for type checking
110+
├─ Executes type-aware rules
111+
└─ Returns structured diagnostics
112+
```
113+
114+
This design keeps Oxlint's core fast while leveraging TypeScript's type system through typescript-go. The frontend-backend separation means `oxlint` controls the user experience while `tsgolint` handles the heavy lifting of type analysis.

0 commit comments

Comments
 (0)