8000 docs: blog post on parserOptions.projectService (#8031) · aryaemami59/typescript-eslint@02ebbe1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 02ebbe1

Browse files
JoshuaKGoldbergJosh-Cenaronami
authored
docs: blog post on parserOptions.projectService (typescript-eslint#8031)
* docs: blog post on parserOptions.projectService * Update packages/website/blog/2023-09-18-parser-options-project-true.md * Better diffs and a bit of streamlining * Account for solo and project references at each scale * Apply suggestions from code review Co-authored-by: Joshua Chen <sidachen2003@gmail.com> * Adjusted vision section * Refreshed blog post for latest versions and names * Real world examples * git checkout main -- packages/website/blog/2023-09-18-parser-options-project-true.md * git checkout main -- docs/packages/Parser.mdx * Lots of touchups * More tweaks * Back-links galore * nit: line length 'own' * allowDefaultProject rename * touch up project refs * Touch up feedback * More proofreading * More proofreading * More proofreading * More proofreading * More proofreading * fix broken link * Shoutout Benn and SvelteKit * Add back tsconfigRootDir * Apply suggestions from code review Co-authored-by: Ronen Amiel <ronen.amiel@gmail.com> * Update packages/website/blog/2025-05-26-project-service.mdx Co-authored-by: Ronen Amiel <ronen.amiel@gmail.com> --------- Co-authored-by: Joshua Chen <sidachen2003@gmail.com> Co-authored-by: Ronen Amiel <ronen.amiel@gmail.com>
1 parent d2ffec7 commit 02ebbe1

File tree

4 files changed

+236
-1
lines changed

4 files changed

+236
-1
lines changed

.cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@
196196
"tsconfigrootdir",
197197
"tsconfigs",
198198
"tseslint",
199+
"tsgo",
199200
"tsvfs",
200201
"typedef",
201202
"typedefs",

docs/packages/Parser.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ Specifies using TypeScript APIs to generate type information for rules.
294294
It will automatically use the nearest `tsconfig.json` for each file (like `project: true`).
295295
It can also be configured to also allow type information to be computed for JavaScript files without the `allowJs` compiler option (unlike `project: true`).
296296

297+
See [Typed Linting with `parserOptions.projectService`](/blog/project-service) for more context.
298+
297299
<Tabs groupId="eslint-config">
298300
<TabItem value="Flat Config">
299301

docs/packages/Project_Service.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ The typescript-eslint Project Service is a wrapper around TypeScript's "project
1616
These APIs are what editors such as VS Code use to programmatically "open" files and generate TypeScript programs for type information.
1717

1818
:::note
19-
See [Announcing typescript-eslint v8 > Project Service](/blog/announcing-typescript-eslint-v8#project-service) for more details on how lint users interact with the Project Service.
19+
See [Blog > Typed Linting with Project Service](/blog/project-service) for more details on how lint users interact with the Project Service.
2020
:::
2121

2222
```ts
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
---
2+
authors: joshuakgoldberg
3+
description: How typescript-eslint's new "Project Service" makes typed linting easier to configure, especially for large projects.
4+
slug: project-service
5+
tags: [parser, parser options, project, project service, tsconfig]
6+
title: Typed Linting with Project Service
7+
---
8+
9+
import Tabs from '@theme/Tabs';
10+
import TabItem from '@theme/TabItem';
11+
12+
["Typed linting"](/blog/typed-linting), or enabling ESLint rules to understand TypeScript types, is one of the best parts of typescript-eslint.
13+
It enables a slew of [more powerful lint rules](/rules/?=recommended-typeInformation) that check for nuanced bugs, best practice violations, and other code issues that can only be detected using type information.
14+
15+
Typed linting hasn't always been straightforward to configure or performant at runtime.
16+
We've seen users have to manage separate `tsconfig.eslint.json` files to enable typed linting — sometimes with different compiler options than the rest of the project.
17+
Not ideal.
18+
19+
In typescript-eslint 8.0, we stabilized a **`parserOptions.projectService`** option that uses more powerful, streamlined TypeScript APIs than before.
20+
The "Project Service" brings several benefits:
21+
22+
- ✍️ **Configuration**: simpler ESLint configs for typed linting with no ESLint-specific TSConfig files
23+
- 🧠 **Predictability**: uses the same type information services as editors, including more reliability
24+
- 🚀 **Scalability**: supporting TypeScript project references for larger repositories (i.e. monorepos)
25+
26+
This blog post will cover how `parserOptions.projectService` simplifies configurations and aligns linting type information to what editors such as VS Code run with.
27+
28+
:::tip
29+
See [Getting Started](/getting-started) to learn how to lint JavaScript and TypeScript code with typescript-eslint, then [Linting with Type Information](/getting-started/typed-linting) to onboard to typed linting.
30+
:::
31+
32+
<!-- truncate -->
33+
34+
## Introducing the Project Service
35+
36+
Back in [Relative TSConfig Projects with `parserOptions.project = true` > Project Services](2023-09-18-parser-options-project-true.md#project-services), we'd mentioned a replacement for `parserOptions.project`:
37+
38+
> The downside of having users specify `parserOptions.project` at all is that `@typescript-eslint/parser` needs manual logic to create TypeScript Programs and associate them with linted files.
39+
> Manual Program creation logic comes with a few issues: ...
40+
>
41+
> We're working on an option to instead call the same TypeScript "Project Service" APIs that editors such as VS Code use to create Programs for us instead.
42+
> Project Services will automatically detect the TSConfig for each file (like `project: true`), and will also allow type information to be computed for JavaScript files without the `allowJs` compiler option (unlike `project: true`).
43+
44+
Following a year of discussion and beta testing in typescript-eslint v6 and v7, we believe the new Project Service API is ready to be used by real-world projects.
45+
We therefore promoted the `parserOptions.EXPERIMENTAL_useProjectService` option to the stable name **`parserOptions.projectService`** in typescript-eslint v8.
46+
47+
:::note
48+
See [Announcing typescript-eslint v8 > Project Service](/blog/announcing-typescript-eslint-v8#project-service) for the original announcement.
49+
:::
50+
51+
## Configuration
52+
53+
You can change over to the new Project Service API by replacing `project` with `projectService` in your ESLint configuration:
54+
55+
<Tabs groupId="eslint-config">
56+
<TabItem value="Flat Config">
57+
58+
```js title="eslint.config.js"
59+
export default tseslint.config({
60+
// ...
61+
languageOptions: {
62+
parserOptions: {
63+
// Remove this line
64+
project: true,
65+
// Add this line
66+
projectService: true,
67+
tsconfigRootDir: import.meta.dirname,
68+
},
69+
},
70+
// ...
71+
});
72+
```
73+
74+
</TabItem>
75+
<TabItem value="Legacy Config">
76+
77+
```js title=".eslintrc.cjs"
78+
module.exports = {
79+
// ...
80+
parser: '@typescript-eslint/parser',
81+
parserOptions: {
82+
// Remove this line
83+
project: true,
84+
// Add this line
85+
projectService: true,
86+
tsconfigRootDir: __dirname,
87+
},
88+
// ...
89+
};
90+
```
91+
92+
</TabItem>
93+
</Tabs>
94+
95+
That's it!
96+
97+
Other settings, including how you run ESLint and configure rules, should work the same.
98+
99+
:::tip
100+
See [Packages > Parser > `projectService`](/packages/parser#projectservice) for more details on granular configuration options.
101+
:::
102+
103+
### Additional Files
104+
105+
One long-standing pain point of typed linting was enabling typed linting for files not included in the project's `tsconfig.json`.
106+
Common solutions in the traditional Program API were to either skip typed linting for those files or to create a `tsconfig.eslint.json` enabling the `allowJs` compiler option.
107+
108+
The new Project Service API allows for a configuration object specifying `allowDefaultProject`: a glob of "out-of-project" files to lint with type information.
109+
That means you can lint those files without any new configuration files or TypeScript compiler options!
110+
111+
For example, the following config solves the common case of projects that have root-level files like `eslint.config.js` or `vitest.config.ts`:
112+
113+
<Tabs groupId="eslint-config">
114+
<TabItem value="Flat Config">
115+
116+
```js title="eslint.config.js"
117+
export default tseslint.config({
118+
// ...
119+
languageOptions: {
120+
parserOptions: {
121+
projectService: {
122+
allowDefaultProject: ['*.js'],
123+
},
124+
tsconfigRootDir: import.meta.dirname,
125+
},
126+
},
127+
// ...
128+
});
129+
```
130+
131+
</TabItem>
132+
<TabItem value="Legacy Config">
133+
134+
```js title=".eslintrc.cjs"
135+
module.exports = {
136+
// ...
137+
parser: '@typescript-eslint/parser',
138+
parserOptions: {
139+
projectService: {
140+
allowDefaultProject: ['*.js'],
141+
tsconfigRootDir: __dirname,
142+
},
143+
},
144+
// ...
145+
};
146+
```
147+
148+
</TabItem>
149+
</Tabs>
150+
151+
This means most projects should be able to remove all `tsconfig.eslint.json` files!
152+
🥳
153+
154+
:::tip
155+
See [Packages > Parser > `projectService` > `ProjectServiceOptions`](/packages/parser#projectserviceoptions) for more details on out-of-project files and other granular configuration options.
156+
:::
157+
158+
## Predictability
159+
160+
We've found configuring `tsconfig.eslint.json` files to be a common source of confusion with the traditional Program APIs.
161+
They can result in the type information used for _linting_ accidentally being different from the type information used for _type checking_.
162+
Unifying TypeScript configurations to the same `tsconfig.json` file(s) altogether avoids potential divergent types.
163+
164+
Another benefit of using the new Project Service API is that typed linting requires no additional work in typescript-eslint for more difficult uses of ESLint and/or TypeScript.
165+
We sometimes had to de-optimize the traditional Program API to support use cases:
166+
167+
- CLI `--fix` mode would lose type information after the first pass ([#9577](https://github.com/typescript-eslint/typescript-eslint/pull/9577))
168+
- Extra file extensions such as `.svelte` and `.vue` were not supported at all ([#9504](https://github.com/typescript-eslint/typescript-eslint/issues/9504))
169+
170+
The new Project Service API does not suffer from these issues.
171+
It supports extra file extensions out-of-the-box and does not slow down when used with ESLint's `--fix`.
172+
173+
## Scalability
174+
175+
[TypeScript's project references](https://www.typescriptlang.org/docs/handbook/project-references.html) are how many larger projects, in particular monorepos, scale TypeScript type checking.
176+
They allow delineating discrete projects with their own `tsconfig.json` files and annotating which projects depend on which other projects.
177+
TypeScript is able to cache type information and only recheck projects that have changed in builds based on those project references.
178+
179+
The traditional `parserOptions.project` API did not support project references for typed linting.
180+
We had experimented with adding support, but using the manual built-in TypeScript APIs would have been a significant maintenance investment with an unclear payoff.
181+
182+
The new Project Service API does support project references out-of-the-box.
183+
This is a huge win for monorepos, as it means you can lint all of your projects with type information without needing to create a separate `tsconfig.eslint.json` file for each project.
184+
185+
## Performance
186+
187+
Supporting project references allows the new Project Service API to be significantly faster than the traditional `parserOptions.project` API in many monorepo cases.
188+
We've observed improvements for typed linting speed in real-world repositories [^babel-conversion] [^create-t3-app-conversion] [^sveltekit-conversion].
189+
For smaller projects, the performance of the new Project Service API is similar to the traditional `parserOptions.project` API.
190+
191+
When we first started working with the new project service API, it outperformed equivalent `parserOptions.project` setups by ~10-15%.
192+
Since then, we have observed regressions in performance that have brought it down in some cases to be slightly slower.
193+
194+
We believe the new Project Service API should be faster than the traditional API, and are treating the lack of significant improvement as a bug.
195+
See [⚡ Performance: parserOptions.projectService sometimes no longer outperforms parserOptions.project](https://github.com/typescript-eslint/typescript-eslint/issues/9571) for more information.
196+
197+
## Next Steps
198+
199+
The new Project Service API is available in typescript-eslint v8.0.0 and later.
200+
We've been using it in our monorepo for over a year and have been thrilled to see many community repositories adopt it as well.
201+
202+
### Giving Feedback
203+
204+
We'd love to hear from you on how this option works for you.
205+
Does it live up to what we've promised, and/or does it have bugs we haven't fixed yet?
206+
Please do send us GitHub issues for any bugs you encounter or suggestions for how to improve the API.
207+
208+
The [typescript-eslint Discord](https://discord.gg/FSxKq8Tdyg) is a great place to ask questions and engage with us more casually.
209+
For support in onboarding, feel free to ask in its `#help` channel.
210+
We'd be happy to help you try out `parserOptions.projectService` and learn more about how you use typescript-eslint.
211+
212+
### Long Term Vision
213+
214+
The new Project Service API is a great step towards making typed linting easier and more straightforward to configure.
215+
Our priority for the next year will be to improve the new Project Service API so that it works in all places the traditional Program API does.
216+
We won't remove the traditional project program behavior unless and until the new Project Service API is able to fully replace it.
217+
218+
As of typescript-eslint@8.33.0, we've also extracted most of the Project Service code into a standalone [`@typescript-eslint/project-service`](/packages/project-service) package.
219+
It has no dependencies on ESLint and is designed to be usable for any linter to enable TypeScript's Project Service API for typed linting.
220+
See [Packages > Project Service](/packages/project-service) for more details.
221+
222+
We're also looking forward to investigating support for [TypeScript's 10x faster Go port](https://github.com/typescript-eslint/typescript-eslint/issues/10940).
223+
Abstracting configuration details into the Project Service API means it will be much easier for typescript-eslint to support typed linting using "tsgo" without any additional user configuration.
224+
225+
So, please, try out the new Project Service API.
226+
We're excited to hear how it works for you and what we can do to improve it. 💜
227+
228+
[^babel-conversion]: https://github.com/babel/babel/pull/16192#issue-2054613116
229+
230+
[^create-t3-app-conversion]: https://github.com/t3-oss/create-t3-app/pull/1936/#discussion_r1667389041
231+
232+
[^sveltekit-conversion]: https://github.com/sveltejs/kit/pull/13839

0 commit comments

Comments
 (0)
0