Skip to content
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

Tsconfig includes not recognized (typescript-eslint@2.0.0) #853

Closed
sem4phor opened this issue Aug 14, 2019 · 23 comments · Fixed by #866
Closed

Tsconfig includes not recognized (typescript-eslint@2.0.0) #853

sem4phor opened this issue Aug 14, 2019 · 23 comments · Fixed by #866
Labels
documentation Documentation ("docs") that needs adding/updating has pr there is a PR raised to close this package: parser Issues related to @typescript-eslint/parser

Comments

@sem4phor
Copy link

What code were you trying to parse?

Vue files (see https://github.com/sem4phor/vue-typescript-eslint-bug)

What did you expect to happen?

Parser lints files specified in tsconfig->include

What actually happened?

I have to add extraFileExtensions: [".vue"] in .eslintrc.js to lint vue files even its declared in include option in tsconfig.json

And for all .js files the Parser says:

...
error: Parsing error: If "parserOptions.project" has been set for @typescript-eslint/parser, /Users/semaphor/Projekte/test/.eslintrc.js must be included in at least one of the projects provided at .eslintrc.js:
...

Reproduction:

  • git clone git@github.com:sem4phor/vue-typescript-eslint-bug.git
  • navigate to folder
  • npm i
  • npm run lint

Moreover eslint is not able to parse vue template section of single file components since upgrade of typescript eslint. But i guess thats more a problem of eslint-plugin-vue.

Versions

package version
@typescript-eslint/parser 2.0.0
TypeScript 3.4.3
ESLint 5.16.0
node 11.6.0
npm 6.10.2
@sem4phor sem4phor added package: parser Issues related to @typescript-eslint/parser triage Waiting for maintainers to take a look labels Aug 14, 2019
@0x80
Copy link

0x80 commented Aug 14, 2019

I don't think this is Vue specific. I'm experiencing the same problem with my Next.js project. I would suggest to take Vue out of the title.

@sem4phor sem4phor changed the title Vue project: Tsconfig includes not recognized (typescript-eslint@2.0.0) Tsconfig includes not recognized (typescript-eslint@2.0.0) Aug 14, 2019
@gho1b
Copy link

gho1b commented Aug 14, 2019

Yeh, i

I don't think this is Vue specific. I'm experiencing the same problem with my Next.js project. I would suggest to take Vue out of the title.

I got equal issue with jest mockup and snapshot files

@mrestorff
Copy link

mrestorff commented Aug 14, 2019

I don't think this is Vue specific.

Can confirm, this issue occurs in my Bot Framework project as well.

Edit: It went away when I changed an unrelated option in my ESLint config.

@bradzacher
Copy link
Member

@0x80, @gho1b, @mrestorff and anyone else who chooses to comment here.

Please provide details about your setups to help us investigate any problems, as 1 line comments don't really tell us anything about the problem.

We don't want to have to go and google everything about your specific use case, as that's not scalable or maintainable for us, as we are volunteers.

Help us to help you.

Post your eslint config, your tsconfig, code samples, links to repos, etc. Anything and everything that you think might help.


@gho1b - jest snapshot files are not something we parse. So I need more information about what your setup looks like.


@sem4phor we have an integration test setup for vue projects here. Could you please compare that against your current setup and let me know if there's anything different?

https://github.com/typescript-eslint/typescript-eslint/tree/master/tests/integration/fixtures/vue-sfc

@0x80
Copy link

0x80 commented Aug 14, 2019

@bradzacher Sorry for assuming the problem was somehow obvious. In my case the problem occurs as part of a Next.js project. I have the following config:

tsconfig.json

{
  "compilerOptions": {
    "esModuleInterop": true,
    "jsx": "preserve",
    "lib": ["dom", "esnext"],
    "module": "esnext",
    "moduleResolution": "node",
    "noEmit": true,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "preserveConstEnums": true,
    "removeComments": false,
    "skipLibCheck": true,
    "sourceMap": true,
    "strict": true,
    "target": "esnext",
    "allowJs": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true
  },
  "exclude": ["node_modules"],
  "include": ["next-env.d.ts", "**/*.js", "**/*.ts", "**/*.tsx"]
}

eslintrc.js

module.exports = {
  parser: "@typescript-eslint/parser",
  parserOptions: {
    project: "./tsconfig.json", // required for rules that need type information
    ecmaVersion: 2018,
    sourceType: "module",
    ecmaFeatures: {
      jsx: true
    }
  },
  extends: [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier",
    "prettier/@typescript-eslint"
  ],
  rules: {
    "no-console": ["error", { allow: ["error", "log"] }],
    "no-empty": "off",
    "react/prop-types": "off", // seems to clash
    "@typescript-eslint/no-floating-promises": "error",
    "@typescript-eslint/no-non-null-assertion": "off",
    "@typescript-eslint/no-use-before-define": "off",
    "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
    "@typescript-eslint/camelcase": "off",
    "@typescript-eslint/explicit-function-return-type": "off"
  },
  settings: {
    react: {
      version: "detect" // Tells eslint-plugin-react to automatically detect the version of React to use
    }
  }
};

ESlint starts giving me the error (as described by @sem4phor) but only on Javascript files that I have mixed with my Typescript ones. It does not complain about the Typescript files.

@Bluefinger
Copy link

Bluefinger commented Aug 14, 2019

Having same issue with regards to the new parser having a fit on any .js files on a personal project (haven't uploaded to github yet). Seeing no issues with .ts files, but .js files are having the same error as described here. The only thing that changed was upgrading to v2.0.0 from v1.13.0. The project is pretty much pure typescript, no frameworks being used so it is definitely an issue with the parser.

tsconfig.json

{
  "compilerOptions": {
    "baseUrl": "./src",
    "incremental": true,
    "tsBuildInfoFile": "./.cache/tsBuildInfo",
    "sourceMap": true,
    "strict": true,
    "noUnusedLocals": true,
    "esModuleInterop": true,
    "module":"esnext",
    "moduleResolution": "node",
    "rootDir": "./src"
  },
  "include": [
    "./src/**/*"
  ]
}

rollup.config.umd.js (seeing the parsing error on root level)

import typescript from "rollup-plugin-typescript2";
import { terser } from "rollup-plugin-terser";

export default {
  input: ["./src/index.ts"],
  plugins: [
    typescript({
      tsconfig: "./tsconfig.json"
    }),
    terser({
      output: {
        ecma: 5
      },
      mangle: {
        properties: {
          regex: /^(_|\$\$)/
        }
      }
    })
  ],
  output: {
    file: "./dist/umd/lib.min.js",
    format: "umd",
    name: "MyLib",
    sourcemap: true
  }
};

.eslintrc.json

{
  "root": true,
  "parser": "@typescript-eslint/parser",
  "extends": [
    "plugin:@typescript-eslint/recommended",
    "plugin:prettier/recommended",
    "prettier/@typescript-eslint"
  ],
  "env": {
    "browser": true,
    "es6": true
  },
  "plugins": ["@typescript-eslint", "prettier"],
  "parserOptions": {
    "project": "./tsconfig.json",
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "rules": {
    "@typescript-eslint/no-explicit-any": "off",
    "@typescript-eslint/explicit-function-return-type": "off",
    "@typescript-eslint/no-this-alias": "off"
  }
}

Versions:

package version
node 12.7.0
npm 6.10.2
Eslint 6.1.0
Typescript 3.5.3
parser 2.0.0
rollup 1.19.4

@bradzacher
Copy link
Member

@Bluefinger, @0x80.

Please try adding compilerOptions.allowJs to your tsconfig.json.
IIRC the TypeScript compiler requires this to parse JS files.
LMK if that fixes the issue for you.

cc @uniqueiniquity / @JamesHenry.
Should we automatically override this flag to be true?
It seems like the functionality of ignoring js files matched by include without this flag is going to be a bit of a hurdle to overcome.

@favna
Copy link

favna commented Aug 15, 2019

It is also described on the @typescript-eslint/eslint-plugin page but you could also make a tconfug.eslint.json, target than in eslintrc and have it extend your base tsconfig. That way you can allowJS and include non-source files (I.e. tests) while not dirtying your build.

@gho1b
Copy link

gho1b commented Aug 15, 2019

@bradzacher i has done to solve the snap files after exclude generated files from eslint. But the issue still happen for config files (*.config.js, *.mockup.js, etc). This is my tsconfig and eslintrc

{
  "compilerOptions": {
    "target": "esnext",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true
  },
  "exclude": [
    "node_modules",
    "dist",
    ".next",
    "out",
    "next.config.js",
    "apolo-env.d.ts"
  ],
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ]
}
{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": "./tsconfig.json",
    "ecmaVersion": 2019,
    "sourceType": "module"
  },
  "plugins": [
    "graphql"
  ],
  "extends": [
    "airbnb",
    "plugin:react/recommended",
    "plugin:prettier/recommended",
    "prettier/react",
    "prettier/@typescript-eslint",
    "plugin:jest/recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "rules": {
    "@typescript-eslint/indent": [
      "error",
      2
    ],
    "@typescript-eslint/no-unused-vars": [
      "error",
      {
        "vars": "all",
        "args": "after-used",
        "ignoreRestSiblings": false
      }
    ],
    "@typescript-eslint/semi": [
      "error"
    ],
    "import/no-extraneous-dependencies": [
      "error",
      {
        "devDependencies": [
          "**/__tests__/*.test.ts",
          "**/__tests__/*.test.tsx"
        ]
      }
    ],
    "jsx-a11y/anchor-is-valid": [
      "error",
      {
        "components": [
          "Link"
        ],
        "specialLink": [
          "hrefLeft",
          "hrefRight"
        ],
        "aspects": [
          "invalidHref",
          "preferButton"
        ]
      }
    ],
    "linebreak-style": 0,
    "max-len": [
      "error",
      {
        "code": 120,
        "ignoreComments": true,
        "ignoreTrailingComments": true,
        "ignoreStrings": true,
        "ignoreRegExpLiterals": true
      }
    ],
    "no-underscore-dangle": [
      "off"
    ],
    "quotes": [
      "error",
      "single",
      {
        "allowTemplateLiterals": true
      }
    ],
    "react/sort-comp": [
      "error",
      {
        "order": [
          "static-methods",
          "everything-else",
          "lifecycle",
          "/^_?handle.+$/",
          "/^_?on.+$/",
          "render",
          "^_?render.+$"
        ],
        "groups": {
          "lifecycle": [
            "displayName",
            "propTypes",
            "contextTypes",
            "childContextTypes",
            "mixins",
            "statics",
            "defaultProps",
            "constructor",
            "getDefaultProps",
            "state",
            "getInitialState",
            "getChildContext",
            "getDerivedStateFromProps",
            "componentWillMount",
            "UNSAFE_componentWillMount",
            "componentDidMount",
            "componentWillReceiveProps",
            "UNSAFE_componentWillReceiveProps",
            "shouldComponentUpdate",
            "componentWillUpdate",
            "UNSAFE_componentWillUpdate",
            "getSnapshotBeforeUpdate",
            "componentDidUpdate",
            "componentDidCatch",
            "componentWillUnmount"
          ]
        }
      }
    ],
    "react/jsx-filename-extension": [
      1,
      {
        "extensions": [
          ".js",
          ".jsx",
          ".ts",
          ".tsx"
        ]
      }
    ],
    "react/jsx-props-no-spreading": ["error", {
      "custom": "ignore"
    }],
    "semi": "off"
  },
  "settings": {
    "import/resolver": {
      "node": {
        "extensions": [
          ".js",
          ".jsx",
          ".ts",
          ".tsx"
        ]
      }
    },
    "react": {
      "pragma": "React",
      "version": "detect"
    }
  },
  "env": {
    "jest": true
  },
  "globals": {
    "window": true,
    "document": true
  }
}

@favna
Copy link

favna commented Aug 15, 2019

@gho1b, you need to include the *.js files, not exclude them in your tsconfig. The easiest way to do this is probably the way they suggest in the readme, make a separate tsconfig.eslint.json, and write it like so:

{
  "extends": "./tsconfig.json",
  "includes": [
      "src",
      "**/*.tsx",
      "**/*.ts",
      "**/*.js",
      "next-env.d.ts"
   ],
    "excludes": [
      "node_modules",
      "dist",
      ".next",
      "out"
    ]
}

Alternatively you can also tell typescript-eslint parser to create a default program to regain pe-v2.x behaviour, see configuration in the readme:
https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser#configuration

@Bluefinger
Copy link

@bradzacher Adding allowJs: true and checkJs: true, then disabling the incremental build, did not work. Again, this configuration worked fine in v1.13.0, but the switch to v2.0.0 caused it to have these errors.

What actually fixed this for me is creating a separate tsconfig.json for eslint, which has to include the files I want to lint, both the JS and TS files, including configuration files. I'm not sure I particularly like this solution as it seems more work just to set up a working configuration.

I'll probably have to do the same with my other projects as well to do this upgrade, but the separate tsconfig approach works for me.

@favna
Copy link

favna commented Aug 15, 2019

@Bluefinger what I told @gho1b also applies to you. You should read the README of the parser package. You can optionally pass the createDefaultProgram option with value true to return to the behaviour the parser had before v2.x. https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser#configuration

@Bluefinger
Copy link

@favna Please keep in mind that the configuration I posted worked pre-v2 (and I read the README previously to get that working originally). I didn't expect the very configuration behaviour to change in a breaking way with the upgrade, considering simply setting an .eslintignore was enough to define what I didn't want getting linted vs what I wanted. Now I have to be even more explicit with a separate tsconfig file that should match other configuration for eslint.

Now I understand what is going on, so thanks for the help.

@sem4phor
Copy link
Author

@bradzacher I checked the sfc-integration test and the relevant difference is that there is no .js file in the test folder. In my repository these files are causing the issues.

@bradzacher
Copy link
Member

bradzacher commented Aug 15, 2019

TL;DR summary:

Either: update your base tsconfig to include all files you want to lint, OR create a new tsconfig.eslint.json which looks something like:

{
  // extend your base config so you don't have to redefine your compilerOptions
  "extends": "./tsconfig.json",
  "include": [
    "src/**/*.ts",
    "test/**/*.ts",
    "typings/**/*.ts"
    // etc
  ],
  // IF (and only if) you have a mixed JS/TS codebase - you should also turn on JS support
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true
  }
}

If you are using non standard file extensions (i.e. .vue files), you should add the following config to your .eslintrc file:

{
  "parserOptions": {
    "extraFileExtensions": [".vue"]
  }
}

For those saying "it worked in 1.x, but it's broken in 2.x". We know. We purposely introduced a breaking change in 2.0.0. It's documented clearly in the 2.0.0 release notes.

This change wasn't done lightly, nor was it done for no reason.

In v1.x, when you performed a lint, essentially this happened (note this only applies when passing in compilerOptions.project):

  1. we initialised the typescript compiler, giving it your tsconfig(s).
  2. the typescript compiler would pre-parse and generate types for all files covered by your tsconfig(s).
  3. eslint would then pass in file paths that matched the glob you provided to the CLI.
    • if the file had already been parsed, we would return the results.
    • if the file HADN'T been parsed yet, we would construct a new typescript program using that file as the root, wait for that to complete, and return the result.

As you can probably guess, that last point absolutely destroyed performance if you provided a "bad" tsconfig file. The typescript compiler does not share any information between each program, meaning there was likely going to be a heck of a lot of duplicated work.

The breaking change we made was simple. Instead of silently (and slowly) handling "unexpected" files, we now throw an error. This alerts you, the user, that you've given us a "bad" config, and gives you the opportunity to review and correct your config so that we can parse everything up-front, and do everything in a very fast manner.

The simplest, and most correct solution is as mentioned in the docs, and by @favna:

  • Create a tsconfig.eslint.json file which extends your base config.
  • Setup the include array in this config so that includes every single file you want to lint. Also make sure you have allowJs: true, if you want to lint js files.

We understand that this is an extra config file, and a bit of extra work on your end, but this is the price to pay for performance.


As @favna points out, we still have the old code paths - it's just been hidden behind a flag. We left this in for one simple reason: in case there was a use case that we missed / cannot support properly. We obviously didn't want to completely break the experience for users whose use case we hadn't thought of.

If you really, really, really want to use this flag, it's likely going to be very, very, very slow.

USING THIS FLAG IS NOT RECOMMENDED. AT ALL. NOT ONE BIT. FOR OBVIOUS REASONS.

@gho1b
Copy link

gho1b commented Aug 15, 2019

@favna Wogh, thank you. Your solutions solve my issue, then i just exclude @typescript-eslint/explicit-function-return-type in my files.

@bradzacher bradzacher added documentation Documentation ("docs") that needs adding/updating and removed triage Waiting for maintainers to take a look labels Aug 15, 2019
@bradzacher bradzacher added the has pr there is a PR raised to close this label Aug 15, 2019
@0x80
Copy link

0x80 commented Aug 15, 2019

@bradzacher AFAICT I already had the right configuration, including all files and having allowJs enabled. So I'm using the flag as a workaround for now.

@tamj0rd2
Copy link

tamj0rd2 commented Aug 17, 2019

I'm using a Typescript/Next.js project. I already have all of the files that I want to be linted in my tsconfig.json. They're all .ts and .tsx files. I have no .js files.

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": false,
    "skipLibCheck": false,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "typeRoots": ["node_modules/@types"]
  },
  "exclude": ["node_modules"],
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}

With this configuration, I get the error described. Setting allowJs to true fixes it which is really perplexing, since I have no js files and don't need to lint any js files.

Here's my eslint config:

  "eslintConfig": {
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
      "project": "./tsconfig.json",
      "tsconfigRootDir": "."
    },
    "plugins": [
      "@typescript-eslint"
    ],
    "extends": [
      "plugin:react/recommended",
      "eslint:recommended",
      "plugin:@typescript-eslint/eslint-recommended",
      "plugin:@typescript-eslint/recommended",
      "plugin:@typescript-eslint/recommended-requiring-type-checking",
      "prettier",
      "prettier/@typescript-eslint"
    ],
    "settings": {
      "react": {
        "version": "detect"
      }
    }
  }

@bradzacher
Copy link
Member

bradzacher commented Aug 19, 2019

We've just merged a change into master which should make this a bit easier and clearer for you all:

  • It will just accept JS files by default without any extra config in your tsconfig file (as long as they're matched by the include, that is).
  • The error message should state that either it's not in a project's include block, or that the file extension config is wrong.

Please give it a try on the canary tag on npm

@geekox86
Copy link

Greetings @bradzacher and thank you for your active support.

I tried the canary (2.0.1-alpha.14) and I noticed that by having "*.js" in the tsconfig.json include all JS files (even in subfolders) get matched instead of only those in the same folder as tsconfig.json.

I was expecting to get error message on JS files in the sub folders. But may be I am wrong?

@geekox86
Copy link

I also just noticed that while using IntelliJ, I created a new JS file but was not matched, although I have glob-like patterns in my tsconfig.json that should get it matched.

@tamj0rd2
Copy link

That's actually the cause of my issue too in vscode. If I create a new file, I get this error. If I stop eslint and run it again, it works as expected. It doesn't seem to automatically lint the new file even though it's part of the glob.

@bradzacher
Copy link
Member

@tamj0rd2 - known issue, see #864

@geekox86 - please follow the steps in #890


Locking this issue to direct further discussion toward #890

@typescript-eslint typescript-eslint locked as resolved and limited conversation to collaborators Aug 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
documentation Documentation ("docs") that needs adding/updating has pr there is a PR raised to close this package: parser Issues related to @typescript-eslint/parser
Projects
None yet
9 participants