-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for Project References #2094
Comments
I came here via #1192 from loopbackio/loopback-next#5590, my primary motivation is to fix out-of-memory errors when linting a sizeable monorepo. As the first step, I created a small monorepo where I can run and debug typescript-eslint, see https://github.com/bajtos/learn-a. To use a dev version of typescript-eslint, I manually created a symlink from my local clone of typescript-eslint to my playground:
Then I modified Finally, I added more logging to What I found: Example sourceFile (click to expand)
As I understand this data structure, it allows us (typescript-estree) to automatically add referenced projects to the list of projects we are aware of. For example, if we have a monorepo with root-level However, it's not clear to me how can this improve eslint's performance and avoid out-of-memory errors. As I understand the current state, there is no API that would allow us to obtain the already-created It seems to me that we need few more improvements in TypeScript API, specifically we need to include @bradzacher what's your take on this? Do you have any more knowledge than would help me to find a way how to implement fix for out-of-memory errors? Would it make sense to send a small pull request to enable |
This is my understanding of how it works: Assume project When we ask typescript to gather types for So in memory we now have the following: Now if we extrapolate this basic example into a fully fledged project, where From my understanding based on what @uniqueiniquity has told me,
This means that we don't ever have to manually parse project I've been doing some thinking about this and was going to start on an implementation, but then ESLint merged their optional chaining representation, so updating to support that has taken priority. Working this functionality into the existing code path will be problematic. To illustrate - another example. Extending the above example to include a 3rd project - project When we attempt to parse a file from Note here that because of the way the user specified the config, we have now made the memory and performance substantially worse because we've parsed the So we have two options:
It might seem like (1) is the best option because it requires the smallest change, however I know that some users have odd setups where they might do something instead like specify So I think that the best course of action here is to implement this functionality behind a brand new configuration style. I was thinking that we can add a new variant of When This can be done via traversing up the directory tree looking for either a
Now that we are automatically resolving the The algorithm would be as follows:
|
See: - angular-eslint/angular-eslint#89 (comment) - angular-eslint/angular-eslint#86 (comment) - https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser#parseroptionsproject - https://github.com/angular-eslint/angular-eslint#migrating-from-codelyzer-and-tslint - typescript-eslint/typescript-eslint#2094
@bradzacher Thank you for a detailed explanation! ❤️
Ah, this is the piece I was missing! I'll try to find some time next week 🤞🏻 to verify this behavior in my playground. Based on this information, it makes me wonder if we need to deal with the complexity of detecting duplicate projects. Let me explain an alternative I am thinking of. In loopback-next, we have a top-level
Now if So I am thinking that perhaps we can tell typescript-eslint users to use the same approach when linting monorepos based on project references?
In my proposal, I would ask such users to create top-level |
A few reasons that I don't think this is the best approach: 1 2 We have an open issue to implement some purging mechanism so that we can purge projects from memory once we've parsed/linted every file (#1718). But this purging would be based on the This also leads into... 3 I know some larger projects have had to resort to splitting their lint runs per project instead of doing a single monorepo run because they just have so many projects or so much code. Yes, this particular issue will likely alleviate this problem for a chunk of those users, but no doubt some of them will still be too large for that approach to work. |
Yeah, I am not surprised that people often misconfigure their projects and then report "silly" issues that are wasting maintainers' time. It makes me wonder if this concern could be alleviated by detecting a problematic setup and reporting a helpful warning or error message?
I see, this is a valid argument 👍🏻
At the moment, we have an eslint-specific TypeScript project covering the entire monorepo and eslint works fine this way (even if it's a bit slow). When I tried to rework eslint configs to use existing TypeScript projects we have for each package, I run into OOM as described in #1192. I guess we are on the edge between projects that are small enough to be handled at once and projects that are way too large to fit into memory. My primary motivation was to get rid of I am happy to leave this feature up to you @bradzacher to implement, you have clearly much better understanding of the problem and the landscape. |
This issue came up as a possible blocker to move to project references several times on my team. perhaps @DanielRosenwasser @andrewbranch @sheetalkamat can assist? I know the typescript team is also using typescript-eslint in their repository, which contains project references. |
Is there any way to workaround the lack of support for project references? I did see this in the docs:
I am following this advice however I still get unexpected errors when I try to run ESLint. Here is a reduced test case: https://github.com/OliverJAsh/typescript-eslint-project-references. $ eslint app/main.ts
/Users/oliverash/Development/typescript-eslint-project-references/app/main.ts
3:5 error Unexpected any value in conditional. An explicit comparison or type cast is required @typescript-eslint/strict-boolean-expressions
✖ 1 problem (1 error, 0 warnings) Note that if I run I'm happy to open a separate issue if you think it's necessary. I just decided to post here because I saw a lot of the issues surrounding project references were merged into this one. |
As a first step, we could add: Right before the call to: This will give memory-wasteful project reference support. One could argue that's much better than having errors for that same scenario. It'll probably go OOM rather fast in large references scenarios. But that could be later optimized with algorithms like the one @bradzacher suggested. I doubt it'll support root tsconfigs with EDIT: just to clarify, I'm not a maintainer here or anything... The above is only a suggestion. |
I had discussed with @uniqueiniquity that |
When I tested That was awesome. That flag is not necessarily only suited for the editing experience. I did have to point typescript-eslint to all the tsconfigs, as it doesn't have the logic to follow and track the references yet, but the experience itself, both in vscode and in the command line, was great (with the flag in-place). |
…renceRedirect See #2094 This is quick-and-dirty to get this out there for some users to see what sort of perf improvements this squeezes out. With the flag turned on: ``` bradzacher@bradzacher-mbp typescript-eslint % DEBUG=typescript-eslint:* yarn eslint ./packages/types/src/index.ts ./packages/eslint-plugin/src/index.ts yarn run v1.22.4 $ /Users/bradzacher/github/typescript-eslint/node_modules/.bin/eslint ./packages/types/src/index.ts ./packages/eslint-plugin/src/index.ts typescript-eslint:typescript-estree:parser parserOptions.project (excluding ignored) matched projects: [ './tsconfig.eslint.json', './tests/integration/utils/jsconfig.json', './packages/eslint-plugin/tsconfig.json', './packages/eslint-plugin-internal/tsconfig.json', './packages/eslint-plugin-tslint/tsconfig.json', './packages/experimental-utils/tsconfig.json', './packages/parser/tsconfig.json', './packages/scope-manager/tsconfig.json', './packages/shared-fixtures/tsconfig.json', './packages/types/tsconfig.json', './packages/typescript-estree/tsconfig.json', './packages/visitor-keys/tsconfig.json' ] +0ms typescript-eslint:typescript-estree:createProjectProgram Creating project program for: /Users/bradzacher/github/typescript-eslint/packages/types/src/index.ts +0ms typescript-eslint:typescript-estree:createWatchProgram File did not belong to any existing programs, moving to create/update. /users/bradzacher/github/typescript-eslint/packages/types/src/index.ts +0ms typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/tsconfig.eslint.json. +0ms typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/tests/integration/utils/jsconfig.json. +1s typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/packages/eslint-plugin/tsconfig.json. +844ms typescript-eslint:typescript-estree:createWatchProgram Found program for file. /users/bradzacher/github/typescript-eslint/packages/types/src/index.ts +2s typescript-eslint:parser:parser Resolved libs from program: [ 'es2017' ] +0ms typescript-eslint:typescript-estree:parser parserOptions.project (excluding ignored) matched projects: [ './tsconfig.eslint.json', './tests/integration/utils/jsconfig.json', './packages/eslint-plugin/tsconfig.json', './packages/eslint-plugin-internal/tsconfig.json', './packages/eslint-plugin-tslint/tsconfig.json', './packages/experimental-utils/tsconfig.json', './packages/parser/tsconfig.json', './packages/scope-manager/tsconfig.json', './packages/shared-fixtures/tsconfig.json', './packages/types/tsconfig.json', './packages/typescript-estree/tsconfig.json', './packages/visitor-keys/tsconfig.json' ] +5s typescript-eslint:typescript-estree:createProjectProgram Creating project program for: /Users/bradzacher/github/typescript-eslint/packages/eslint-plugin/src/index.ts +5s typescript-eslint:typescript-estree:createWatchProgram Found existing program for file. /users/bradzacher/github/typescript-eslint/packages/eslint-plugin/src/index.ts +74ms typescript-eslint:parser:parser Resolved libs from program: [ 'es2017' ] +70ms ✨ Done in 6.50s. ``` With the flag turned off: ``` bradzacher@bradzacher-mbp typescript-eslint % DEBUG=typescript-eslint:* yarn eslint ./packages/types/src/index.ts ./packages/eslint-plugin/src/index.ts yarn run v1.22.4 $ /Users/bradzacher/github/typescript-eslint/node_modules/.bin/eslint ./packages/types/src/index.ts ./packages/eslint-plugin/src/index.ts typescript-eslint:typescript-estree:parser parserOptions.project (excluding ignored) matched projects: [ './tsconfig.eslint.json', './tests/integration/utils/jsconfig.json', './packages/eslint-plugin/tsconfig.json', './packages/eslint-plugin-internal/tsconfig.json', './packages/eslint-plugin-tslint/tsconfig.json', './packages/experimental-utils/tsconfig.json', './packages/parser/tsconfig.json', './packages/scope-manager/tsconfig.json', './packages/shared-fixtures/tsconfig.json', './packages/types/tsconfig.json', './packages/typescript-estree/tsconfig.json', './packages/visitor-keys/tsconfig.json' ] +0ms typescript-eslint:typescript-estree:createProjectProgram Creating project program for: /Users/bradzacher/github/typescript-eslint/packages/types/src/index.ts +0ms typescript-eslint:typescript-estree:createWatchProgram File did not belong to any existing programs, moving to create/update. /users/bradzacher/github/typescript-eslint/packages/types/src/index.ts +0ms typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/tsconfig.eslint.json. +1ms typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/tests/integration/utils/jsconfig.json. +1s typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/packages/eslint-plugin/tsconfig.json. +976ms typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/packages/eslint-plugin-internal/tsconfig.json. +2s typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/packages/eslint-plugin-tslint/tsconfig.json. +1s typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/packages/experimental-utils/tsconfig.json. +1s typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/packages/parser/tsconfig.json. +961ms typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/packages/scope-manager/tsconfig.json. +888ms typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/packages/shared-fixtures/tsconfig.json. +996ms typescript-eslint:typescript-estree:createWatchProgram Creating watch program for /users/bradzacher/github/typescript-eslint/packages/types/tsconfig.json. +561ms typescript-eslint:typescript-estree:createWatchProgram Found program for file. /users/bradzacher/github/typescript-eslint/packages/types/src/index.ts +567ms typescript-eslint:parser:parser Resolved libs from program: [ 'es2017' ] +0ms typescript-eslint:typescript-estree:parser parserOptions.project (excluding ignored) matched projects: [ './tsconfig.eslint.json', './tests/integration/utils/jsconfig.json', './packages/eslint-plugin/tsconfig.json', './packages/eslint-plugin-internal/tsconfig.json', './packages/eslint-plugin-tslint/tsconfig.json', './packages/experimental-utils/tsconfig.json', './packages/parser/tsconfig.json', './packages/scope-manager/tsconfig.json', './packages/shared-fixtures/tsconfig.json', './packages/types/tsconfig.json', './packages/typescript-estree/tsconfig.json', './packages/visitor-keys/tsconfig.json' ] +11s typescript-eslint:typescript-estree:createProjectProgram Creating project program for: /Users/bradzacher/github/typescript-eslint/packages/eslint-plugin/src/index.ts +11s typescript-eslint:typescript-estree:createWatchProgram Found existing program for file. /users/bradzacher/github/typescript-eslint/packages/eslint-plugin/src/index.ts +64ms typescript-eslint:parser:parser Resolved libs from program: [ 'es2017' ] +60ms ✨ Done in 12.26s. ```
Quick-and-dirty exposure of a flag to test this feature #2669 |
I just merged #2669, it'll be live on the canary tag shortly. Turning it on should just require setting Note that this implementation contains no safe-guards for the user, so you will need to be aware of your project tree and configure accordingly to remove duplicates. |
Tested 4.4.2-alpha.1 in https://github.com/AviVahl/ts-tools One small annoyance that I noticed, is that I couldn't specify EDIT: oh, and the "peerDependency" range of the packages doesn't include the alpha versions, so installing canary using npm@7 required passing |
@bradzacher this flag is going to make my coding experience so much nicer. thank you so much. Regarding the root Should probably be noted that those paths can be |
Could we please call out this in https://typescript-eslint.io/linting/typed-linting or the faq page? I spent a whole day debugging why tslint doesn't seem to honor all the references field in my tsconfig and eventually saw this issue 😢 update: and using |
Eep, sad to hear that @shogunsea! Good idea on calling it out in FAQs. Filed #6363, +1. |
Follow up on #2094 (comment)
So I'm guessing that's ^ what was happening under the hood, e.g. if we just set |
I have to disable this 5 rules on our monorepo setup:
error, code, configs
server/lib/monitor/filtering.ts: import { typedKeys } from "shared/utils/collections";
// ...
function withoutNullishAndEmptyStr<T extends GenericRecord>(obj: Nullable<T>): Either<typeof obj, T> {
const res = {} as T;
if (!checkNonNullable(obj)) return undefined as Either<typeof obj, T>;
for (const key of typedKeys<T>(obj)) {
if (obj[key] == null || obj[key] === "") continue;
res[key] = obj[key] as T[keyof T];
}
return res;
} shared/utils/collections.ts: export function typedKeys<T extends GenericRecord, K = keyof T>(collection: T): K[] {
return Object.keys(collection) as K[];
} server/.eslintrc.cjs: module.exports = {
extends: "../.eslintrc.cjs",
parserOptions: {
project: "tsconfig.json",
tsconfigRootDir: __dirname,
sourceType: "module",
},
}; I tried server/tsconfig.json: {
"compilerOptions": {
"composite": true,
// enable latest features
"lib": ["esnext"],
"module": "esnext",
"target": "esnext",
// if TS 5.x+
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#--moduleresolution-bundler
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"noEmit": true,
"moduleDetection": "force",
// "jsx": "react-jsx", // support JSX
"allowJs": true, // allow importing `.js` from `.ts`
"esModuleInterop": true, // allow default imports for CommonJS modules
// best practices
"strict": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"paths": {
"shared/*": ["../shared/*"],
"@front/*": ["../src/*"]
},
"baseUrl": ".",
"plugins": [
{ "name": "typescript-styled-plugin", "validate": false },
// Fix import absolute paths
{ "transform": "typescript-transform-paths", "useRootDirs": true } // Transform paths in output .js files
// { "transform": "typescript-transform-paths", "useRootDirs": true, "afterDeclarations": true } // Transform paths in output .d.ts files (Include this line if you output declarations files)
],
"rootDirs": [".", "../src", "../shared"],
"types": ["jest"],
"resolveJsonModule": true
},
"ts-node": { /*...*/ },
"include": [
"./**/*",
"./.eslintrc.cjs",
"../jest.config.ts",
// Don't include: "../src/utils/**/*", As it have browser specific, like utils/hooks.ts
"../src/**/types.ts",
"../src/**/config.ts",
"../src/**/*.types.ts",
"../src/**/*.d.ts",
"../shared/**/*"
],
"references": [{ "path": "../shared/tsconfig.json" }, { "path": "../src/tsconfig.json" }]
} .eslintrc.cjs: module.exports = {
root: true,
extends: [
"react-app",
"react-app/jest",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
],
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint", "unused-imports"],
rules: {
"max-len": ["warn", { code: 120, ignoreComments: true, ignoreUrls: true }],
indent: [
"warn",
2,
{
SwitchCase: 1,
offsetTernaryExpressions: true,
},
],
"@typescript-eslint/ban-ts-ignore": "off", // It deprecated and renamed to @typescript-eslint/ban-ts-comment
"react-hooks/exhaustive-deps": [
"warn",
{
additionalHooks:
"(useAsyncEffect|useCallbackDebounce|useCallbackThrottle|useDidUpdate|useMemoVal|useSyncRefState)",
},
],
//
// Setup unused-imports
"@typescript-eslint/no-unused-vars": ["off"],
"no-unused-vars": "off", // or "@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{
vars: "all",
varsIgnorePattern: "^_",
args: "after-used",
argsIgnorePattern: "^_\\d?$",
ignoreRestSiblings: true,
},
],
},
}; versions (latest)node v16.16.0 |
Hello guys, I understand that supporting TS Project References goes well beyond this, but is there a half-way solution to be able to lint code in a monorepo without needing to build packages? In other scenarios (like with Jest and Webpack) we use aliases to point to the source code directory instead of the built one (that does not exist), so all packages act as one and there is no need to build anything. |
Hey @ernestostifano! I'm currently using it like that. In my experience everything works as expected as long as:
It might be that I'm not hitting certain edge cases though. But I was experiencing issues before and this configuration resolved them, so I thinks it's good enough. P.S: Though performance is probably worse that it should be |
Hi @swandir, thanks for your response! I tried your suggestions and it seems to be working fine. At first, to list all references explicitly in But then I tried without explicitly listing all references and it seems to work too. This is my config now: parserOptions: {
sourceType: 'module',
ecmaVersion: 'latest',
tsconfigRootDir: __dirname,
project: './packages/*/tsconfig.json',
EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true
} |
Yeah, it appears to work if compilerOptions do not differ between tsconfigs. However, compilerOptions may affect type info gathered by the plugin. And when linting a file, the plugin seems to grab the first tsconfig from parserOptions.project what matches the file. Where "matcher the file" means that the file is a part of TS's compilation for this tsconfig. The issue is, the plugin does not use TS's build mode. So all the files from dependent-upon TS projects (referenced tsconfigs) are part of the same compilation. As a result files may end up matched with wrong tsconfigs. But as long as dependent-upon tsconfigs appear in the list before their dependencies, the plugin will see the correct tsconfig first. I can be wrong on the exact details here, but this is how it appears to work. |
So I've tried enabling the new EXPERIMENTAL_useProjectService option implemented in #6754 in my repro from #2094 (comment) Now type-aware rules produce consistent results regardless of declaration files presence, yay! |
Confirmed that the experimental flag fixes it as well! |
Thanks for this new Here's how I used it in the new ESLint Flat Config format (in the (
import eslintTypescript from '@typescript-eslint/eslint-plugin';
import typescriptParser from '@typescript-eslint/parser';
/** @type {import('@typescript-eslint/utils/ts-eslint').FlatConfig.ConfigArray} */
const configArray = [
{
files: ['**/*.js', '**/*.jsx', '**/*.cjs', '**/*.mjs', '**/*.ts', '**/*.tsx', '**/*.cts', '**/*.mts'],
languageOptions: {
parser: typescriptParser,
parserOptions: {
project: './tsconfig.json',
// typescript-eslint specific options
warnOnUnsupportedTypeScriptVersion: true,
EXPERIMENTAL_useProjectService: true,
},
},
plugins: {
'@typescript-eslint': {
rules: eslintTypescript.rules,
},
},
settings: {
'import/resolver': {
// Load <rootdir>/tsconfig.json
typescript: {
// Always try resolving any corresponding @types/* folders
alwaysTryTypes: true,
},
},
},
rules: {
// Warn on dangling promises without await
'@typescript-eslint/no-floating-promises': ['warn', { ignoreVoid: false }],
},
},
];
export default configArray;
{
"$schema": "https://json.schemastore.org/tsconfig",
"files": [],
"references": [
{ "path": "./tsconfig.root.json" },
{ "path": "./scripts/tsconfig.json" }
]
}
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"composite": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"target": "ES2015",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"resolveJsonModule": true,
"esModuleInterop": true,
"isolatedModules": true,
"allowJs": true,
"allowSyntheticDefaultImports": true,
"downlevelIteration": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true,
"strict": true,
"incremental": true,
"noUncheckedIndexedAccess": true
},
"include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.cjs", "**/*.mjs"],
"exclude": ["node_modules", "scripts"]
}
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"composite": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"target": "ESNext",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"resolveJsonModule": true,
"esModuleInterop": true,
"isolatedModules": true,
"allowJs": true,
"allowSyntheticDefaultImports": true,
"downlevelIteration": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true,
"strict": true,
"incremental": true,
"noUncheckedIndexedAccess": true,
"checkJs": true
},
"include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.cjs", "**/*.mjs"],
"exclude": ["node_modules"]
} |
There was no strong reason for maintaining project references, especially because some of the tooling doesn't support it. By using a single config we make TypeScript checks faster and tools aren't running into problems. - TypeScript ESLint: typescript-eslint/typescript-eslint#2094 - eslint-import-resolver-typescript: typescript-eslint/typescript-eslint#2094 - Vitest: vitest-dev/vitest#3752 - Remix also didn't work, but I wasn't able to find the issue, probablt esbuild So that's at least 4 tools not working. 😄
I can also confirm that #6754 makes project references work on our codebase. Until last week we didn't even know it was not supported, because the referenced projects were built 99% of the time, and then ESLint works as expected. Then we run into a bunch of illogical type errors (a lot warnings about any, ...) that indicated that somehow the ESLint-TS communication got broken, and we couldn't pinpoint the cause for 3 days... until we ultimately found that the difference was (not) having the dependency project build ahead of linting. This is currently very nu-intuitive, there is no warning or errors when TS projects references are used (without the EXPERIMENTAL_useProjectService flag), you just get weird linting results... |
I work on a reasonable sized typescript monorepo using internal ts packages that get compiled by the end product using the packages (like nextjs for example), so the packages don't compile themselves. This was working fine with eslint unil we migrated everything to use es modules. After that we were getting terrible performance, mainly with the eslint vs code extension, taking minutes to lint a single file. Using |
Is it just me, or does creating a new file with |
@fire332 yes, please file an issue! I think I have been experiencing similar behavior in a project that uses New files or renamed files cause the following
|
Can confirm that EXPERIMENTAL_useProjectService in my root eslintrc fixes the issue completely, despite the root eslintrc not including any of my packages' tsconfig's! |
Glad to hear that At this point, we can consider this issue for the specific request of supporting project references resolved. If you have any problems using the experimental project service, please search for existing issues, and if it's not yet filed, file a new issue. Some relevant existing issues & PRs are:
Closing and locking this thread as it's gotten quite long and hard to read through. Thanks everyone! 💜 |
Currently, we do not respect project references - the TS compiler APIs we use do not respect them, and we try to avoid doing tsconfig parsing directly ourselves.
This means that when two projects depended on one-another via project references, we create a program for project
A
, causing TS to load the.ts
files for projectA
, and.d.ts
files for projectB
. Then we create a program for projectB
, causing TS to load the.ts
files for projectB
.This obviously wastes time and memory on duplicated work (the
.d.ts
files) (#1192), and makes it harder to work on and lint two separate but referenced projects simultaneously, as you have to rebuild one to lint the other (#1973).We currently do not have a good solution for this right now because the way projects work in TS isn't exposed to us in the APIs that we use. We'll have to build something - though what that is exactly we don't have a clear picture of.
Note that the way we work is different to TS. TS will build and check one project at a time when you run the CLI, whereas we will "build" every single project required to lint your codebase - meaning we are subject to different constrains compared to TS.
Likely there would need to be work done within TS itself so that it can deduplicate and manage things for us.
There are really two ways we can go about this:
parserOptions.project
entries.The text was updated successfully, but these errors were encountered: