Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
31f96a0
Add Type-Aware Linting Alpha blog post
Boshen Nov 13, 2025
9b8b78e
first pass
camc314 Nov 15, 2025
36cc3d5
Add features
camchenry Nov 15, 2025
f699974
Fix code block
camchenry Nov 15, 2025
cf4d567
Update post
camchenry Dec 2, 2025
730d399
Fix minor wording and formatting issues in blog post
camchenry Dec 2, 2025
a4c096c
Add known issues
camchenry Dec 2, 2025
544ea8a
adds whats next and try it out section
camc314 Dec 4, 2025
2b3aee4
rephrase note
camc314 Dec 4, 2025
9d1a2c4
rephrase note
camc314 Dec 4, 2025
87ae020
format code block
camc314 Dec 4, 2025
3563232
rephrase
camc314 Dec 4, 2025
8f84e80
add note about automated fixes
camc314 Dec 4, 2025
7a4dd5d
add note in diagram about non type aware rules/custom plugins
camc314 Dec 4, 2025
c8fc84e
add note about keeping up to date with tsgo
camc314 Dec 4, 2025
deeaaec
minor phrasing update, code fmt
camc314 Dec 4, 2025
edf76d2
dprint
camc314 Dec 4, 2025
1ba20bd
add placeholder perf section
camc314 Dec 4, 2025
42a160a
add yarn to quickstart
camc314 Dec 4, 2025
4be25de
fix repo name
camc314 Dec 4, 2025
7e73f09
update phrasing
camc314 Dec 4, 2025
b4e6e09
u
camc314 Dec 4, 2025
dc1f437
u
camc314 Dec 4, 2025
15a8aba
u
camc314 Dec 4, 2025
9414a61
update try it out
camc314 Dec 4, 2025
6d879aa
add benchmarks
camc314 Dec 4, 2025
5b8927a
move perf section up below quick start
camc314 Dec 4, 2025
d768828
move known issues section up into performance section
camc314 Dec 4, 2025
2b49ee5
remove the previous behaviour section for new features
camc314 Dec 4, 2025
a146f9f
update inline disable comment section title
camc314 Dec 4, 2025
d1e39fc
link to rule docs
camc314 Dec 4, 2025
32bd0a8
add acknowledgements
camc314 Dec 4, 2025
daba3bb
add more details to feedback section
camc314 Dec 4, 2025
8d3d317
update type aware guide
camc314 Dec 4, 2025
373d2e7
u
camc314 Dec 4, 2025
f578265
lint
camc314 Dec 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vitepress/config/inlined-scripts/banner.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
}
};

window.__OXC_BANNER_ID__ = "/blog/2025-12-01-oxfmt-alpha";
window.__OXC_BANNER_ID__ = "/blog/2025-12-01-type-aware-alpha";
restore(`oxc-banner-dismissed-${__OXC_BANNER_ID__}`, "banner-dismissed");
})();
4 changes: 2 additions & 2 deletions .vitepress/sidebar.blog.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[
{
"text": "Oxfmt Alpha",
"link": "/blog/2025-12-01-oxfmt-alpha"
"text": "Type-Aware Linting Alpha",
"link": "/blog/2025-12-01-type-aware-alpha"
},
{
"text": "Oxlint JS Plugins Preview",
Expand Down
4 changes: 2 additions & 2 deletions .vitepress/theme/components/Banner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const hide = () => {
};

// Sync with inlined-scripts/banner.js
const slug = "/blog/2025-12-01-oxfmt-alpha";
const slug = "/blog/2025-12-01-type-aware-alpha";

const bannerDismissed = useLocalStorage<boolean>(`oxc-banner-dismissed-${slug}`, false);

Expand Down Expand Up @@ -46,7 +46,7 @@ const dismiss = () => {

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

<button type="button" @click="dismiss">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
Expand Down
249 changes: 249 additions & 0 deletions src/blog/2025-12-01-type-aware-alpha.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
---
title: Type-Aware Linting Alpha
outline: deep
authors:
- cameron
- camchenry
---

<AppBlogPostHeader />

<br>

We're excited to announce the alpha release of type-aware linting in Oxlint!

## Overview

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.

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.

**In this post:**

- [Quick Start](#quick-start) - Get started with type-aware linting in minutes
- [Performance](#performance) - See how much faster type-aware linting is compared to ESLint
- [What's new since the technical preview](#what-s-new-since-the-technical-preview) - New features and improvements
- [Technical details](#technical-details) - How type-aware linting works under the hood
- [What's next](#what-s-next) - Upcoming improvements for the beta release

## Quick Start

Install `oxlint` and `oxlint-tsgolint`, then run with the `--type-aware` flag:

::: code-group

```sh [npm]
npm add -D oxlint oxlint-tsgolint@latest
npx oxlint --type-aware
```

```sh [pnpm]
pnpm add -D oxlint oxlint-tsgolint@latest
pnpm oxlint --type-aware
```

```sh [yarn]
yarn add -D oxlint oxlint-tsgolint@latest
yarn oxlint --type-aware
```

```sh [bun]
bun add -D oxlint oxlint-tsgolint@latest
bunx oxlint --type-aware
```

:::

To try a specific type-aware rule without other configuration (`oxlint-tsgolint` must be installed globally or locally already):

::: code-group

```sh [npm]
npx oxlint --type-aware -A all -D typescript/no-floating-promises
```

```sh [pnpm]
pnpx oxlint --type-aware -A all -D typescript/no-floating-promises
```

```sh [yarn]
yarn oxlint --type-aware -A all -D typescript/no-floating-promises
```

```sh [bun]
bunx oxlint --type-aware -A all -D typescript/no-floating-promises
```

:::

For more configuration options, see our [usage guide](/docs/guide/usage/linter/type-aware).

## Performance

| Project | Oxlint + Type Aware | ESLint + typescript-eslint | Improvement |
| --------------- | ------------------- | -------------------------- | ----------- |
| vuejs/core | 2.531 s | 20.800 s | 8.22x |
| outline/outline | 4.448 s | 55.070 s | 12.38x |

Benchmarks were performed on a MacBook Pro M2 Max 12 Cores (8 performance and 4 efficiency).

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.

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..
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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..
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.


:::warning Known Issues
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.
:::

## What's new since the technical preview?

### Support for type-checking while linting

`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.

This is an experimental feature, but you can enable it by adding the `--type-check` and `--type-aware` flag to the `oxlint` command:

```
$ oxlint --type-aware --type-check

× typescript(TS2322): Type 'number' is not assignable to type 'string'.
╭─[index.ts:1:7]
1 │ const message: string = 1
· ───────
╰────
```

### Rule configuration support in `oxlint`

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`:

```json
{
"rules": {
"typescript/no-floating-promises": [
"error",
{
"ignoreVoid": true,
"allowForKnownSafePromises": [
{ "from": "file", "name": "SafePromise" },
{ "from": "lib", "name": "PromiseLike" }
]
}
]
}
}
```

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)).

### In-line disable comment support in `oxlint`

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:

```ts
/* oxlint-disable typescript/no-floating-promises */

// oxlint-disable-next-line typescript/no-floating-promises
[1, 2, 3].map(async (x) => x + 1);
```

### More supported rules

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.

Since the initial preview, support for the following rules has also been added:

- [`no-deprecated`](/docs/guide/usage/linter/rules/typescript/no-deprecated) (one of the most commonly requested rules)
- [`prefer-includes`](/docs/guide/usage/linter/rules/typescript/prefer-includes)
- [`strict-boolean-expressions`](/docs/guide/usage/linter/rules/typescript/strict-boolean-expressions)

### TypeScript program diagnostics are now reported

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.

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:

```
$ oxlint --type-aware

× typescript(tsconfig-error): Invalid tsconfig
╭─[tsconfig.json:4:3]
3 │ "compilerOptions": {
4 │ "baseUrl": ".",
· ─────────
5 │ "experimentalDecorators": true,
╰────
help: Option 'baseUrl' has been removed. Please remove it from your configuration.
See https://github.com/oxc-project/tsgolint/issues/351 for more information.
```

### Automatic fixes for type-aware rules

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.

## Technical details

### Architecture

Type-aware linting in Oxlint uses a unique two-binary architecture:

```
oxlint CLI (Rust)
├─ Handles file traversal, ignore logic, and diagnostics
├─ Runs non-type-aware rules and custom JS plugins
├─ Passes paths and configuration to tsgolint
└─ Formats and displays results

tsgolint (Go)
├─ Uses typescript-go directly for type checking
├─ Executes type-aware rules
└─ Returns structured diagnostics
```

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.

### TypeScript compatibility

`tsgolint` is based on [typescript-go](https://github.com/microsoft/typescript-go), Microsoft's Go-based rewrite that will become TypeScript v7.0. This means that you might encounter some features which are no longer supported.

**Important compatibility notes:**

- Only TypeScript 7.0+ features are supported
- Pre-7.0 syntax and deprecated features are not supported
- Legacy `tsconfig.json` options like `baseUrl` have been removed in TypeScript 7.0

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.

### Implementation details

`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.

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.

## What's next

We're actively working on the following improvements for the beta release:

- **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.
- **Performance and memory usage improvements** - We're going to continue to optimize performance, especially for very large monorepos.

## Acknowledgements

We'd like to extend our gratitude to:

- The TypeScript team for creating `typescript-go`.
- The `typescript-eslint` team for their heartwarming support.
- [@auvred](https://github.com/auvred) for creating `tsgolint`.
- [@camchenry](https://github.com/camchenry) for continued performance work, as well as implementing rule option support.

## Try it out

Ready to get started? Head to the [Quick Start](#quick-start) section above to install and run type-aware linting.

We'd love to hear your feedback on type-aware linting and are excited to see how it helps improve your development workflow.

Connect with us:

- **Discord**: Join our [community server](https://discord.gg/9uXCAwqQZW) for real-time discussions
- **GitHub**: Share feedback on [GitHub Discussions](https://github.com/oxc-project/oxc/discussions)
- **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).
25 changes: 19 additions & 6 deletions src/docs/guide/usage/linter/type-aware.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ Run `oxlint` with `--type-aware`
oxlint --type-aware
```

## Unsupported Features

The following issues will be addressed for the alpha version.

- Auto-fixes for type-aware rules only work in the VS Code extension, not in the CLI (`oxlint --fix`)

## Unimplemented Rules

See https://github.com/oxc-project/tsgolint/issues/104
Expand Down Expand Up @@ -99,3 +93,22 @@ tsgolint is based on [typescript-go](https://github.com/microsoft/typescript-go)
- 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

For help migrating deprecated tsconfig options, see the [TypeScript migration guide](https://github.com/microsoft/TypeScript/issues/62508#issuecomment-3348649259).

## Architecture

Type-aware linting in Oxlint uses a unique two-binary architecture:

```
oxlint CLI (Rust)
├─ Handles file traversal, ignore logic, and diagnostics
├─ Runs non-type-aware rules and custom JS plugins
├─ Passes paths and configuration to tsgolint
└─ Formats and displays results

tsgolint (Go)
├─ Uses typescript-go directly for type checking
├─ Executes type-aware rules
└─ Returns structured diagnostics
```

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.