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

Support for mixed JS and TS codebases - do not lint JS files #109

Closed
marekdedic opened this issue Jan 21, 2019 · 21 comments
Closed

Support for mixed JS and TS codebases - do not lint JS files #109

marekdedic opened this issue Jan 21, 2019 · 21 comments
Labels
documentation Documentation ("docs") that needs adding/updating package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin

Comments

@marekdedic
Copy link
Contributor

marekdedic commented Jan 21, 2019

Repro

JavaScript file (gulpfile.js):

/* eslint-env node */

const gulp = require('gulp');
{
	"parser": "@typescript-eslint/parser",
	"parserOptions": {
		"ecmaVersion": 3
	},
	"env": {
		"browser": true
	},
	"plugins": [
		"@typescript-eslint"
	],
	"extends": "plugin:@typescript-eslint/recommended"
}

Expected Result

I have a package with mostly TypeScript, but also a gulpfile.js, which is plain old JavaScript. I was expecting this plugin to only lint the TypeScript files

Actual Result

For the gulpfile:
error Require statement not part of import statement @typescript-eslint/no-var-requires

Additional Info

I suppose this applies to any mixed codebase containing JS and TS together

Versions

package version
@typescript-eslint/eslint-plugin 1.0.0
@typescript-eslint/parser 1.0.0
TypeScript 3.2.4
ESLint 5.12.1
node 11.7.0
npm 6.6.0
@marekdedic marekdedic added package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for maintainers to take a look labels Jan 21, 2019
@marekdedic marekdedic changed the title Support for mixed js and ts codebases Support for mixed JS and TS codebases - do not lint JS files Jan 21, 2019
@armano2
Copy link
Member

armano2 commented Jan 21, 2019

by default eslint lint all provided files with all rules, you should use overrides if don't want specific files to be linted by some of rules

you can also set // eslint-disable to turn off rules in specific places
https://eslint.org/docs/user-guide/configuring#disabling-rules-with-inline-comments

example of eslint config with overrides:
https://github.com/typescript-eslint/typescript-eslint/blob/master/.eslintrc.json

@marekdedic
Copy link
Contributor Author

marekdedic commented Jan 21, 2019

Hi,
thanks for the blazing quick reply and for the tip.

I can do that, however, since I am asking, wouldn't it make more sense for this plugin to just ignore plain old js files? TypeScript does the same thing. (unless called with --allowJS, I know). - I mean this as a suggestion...

@j-f1
Copy link
Contributor

j-f1 commented Jan 21, 2019

Seems like it might make sense for us to limit some of the rules in the recommended config.

@kaicataldo
Copy link
Member

We had a similar discussion for the recent babel-eslint changes (see babel/babel-eslint#738) about how to handle files that aren't being transformed by Babel.

What we ended up deciding on was the following behavior:

Each time babel-eslint parses a file and no corresponding config file is found, an error will be thrown with an optional opt-out.

Here's the corresponding PR: babel/babel-eslint#743

It could make sense to do something similar here and have an opt-out flag that throws an error (and so would short-circuit this flow before it can run the rules) when parsing is done on a file that doesn't end in .ts or .tsx.

@bradzacher
Copy link
Member

Mixed codebases has come up a number of times, but the answer we always arrive at is the same: if you have a mixed codebase, then it's up to you to decide where your boundaries are, and what rules you apply to what files.

Unless I'm mistaken - we can't apply overrides in the recommended config, because of the precedence of how overrides work (they override the base rules property).
So if we add overrides to only apply rules on .ts{x} files, then when a user wants to turn off a rule, they too have to define this turn off as an override on .ts{x} files (which is clunky, and hard to figure out).

That being said, we could consider exposing a recommended-mixed-codebase config, which does do this.


babel-eslint is different IMO because it requires the babel config, and will crash if misconfigured (i.e. babel parsing a flow file without flow config will not work). (correct me if I'm wrong there).

Our parser requires zero typescript config to work on a .ts, .tsx, .js or .jsx file, in fact AFAIK right now it doesn't even look for a tsconfig.json file.
The rules are the same - they shouldn't break on JS code (in fact, I don't even think that they'll break if you don't use the parser), so there's no reason to turn them off for JS code; unless they don't fit your JS code style.
However if they don't fit your JS code style, then that's your job to configure eslint to fit your codebase.


As an aside - in this instance of a gulpfile, you should actually be able to write it as a ts file! (https://gulpjs.com/docs/en/getting-started/javascript-and-gulpfiles)

@bradzacher
Copy link
Member

An example I like to think of is the rule import/no-nodejs-modules.
If I build and publish a config for react codebases that has that rule turned on, that seems good right? We can ensure that nobody accidentally imports a nodejs builtin module within their code which runs in a browser.

But what happens when within my project, I decide to write a cli build tool which needs access to fs or path?
The rule will obviously flag that usage within that file, even though I don't want it to because the code is not browser-run code.

It's not a bug in the config, or a bug in the rule, it's a problem in my specific setup - eslint or the config doesn't know, nor does it care that this new file is not run in the browser.

Thus I have to modify my local config to suit my project's setup.

@j-f1 j-f1 added package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin and removed package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for maintainers to take a look labels Jan 23, 2019
@markogresak
Copy link

markogresak commented Feb 10, 2019

The problem is that overrides do not allow extends property. The only workaround I found is to add an override for .js, and .jsx if it's a React project, files to disable all @typescript-eslint rules in recommended.json.
Something like:

{
    "extends": [
        "plugin:@typescript-eslint/recommended",
        // ...
    ],
    // ...
    },
    "overrides": [
        {
            "files": ["*.js", "*.jsx"],
            "rules": {
                // "@typescript-eslint/...": "off",
            }
        }
    ]
}

This is not ideal, because if the recommended.json changes, I have to manually update this again. It's not a huge issue, but it looks dirty.

It would be nice if the rule would work with checkJs config flag in tsconfig.json, if the config file exists. This approach makes tsconfig.json the single source of truth for the preference, without requiring additional configuration or rules to support this exception.

@markogresak
Copy link

Another problem with current recommended config is the disabled rules in favor of the @typescript-eslint counterpart. It might be expected that these rules still work in .js files.
Maybe there could be a CLI helper tool to help find and fix the conflicting rules, like eslint-config-prettier-check, which comes with eslint-config-prettier?

@armano2
Copy link
Member

armano2 commented Feb 10, 2019

@markogresak can you provide example of issue with any rule for js files?
if there are some we should fix them, rather than trying to patch it witch over complicated configuration

no-var-requires is enabled for now as good practice in typescript.


upgrade tool is nice idea

@markogresak
Copy link

@armano2 sorry, I messed up my configuration a bit wrong and got some problems related to my project and config, not the @typescript-eslint itself.

For the rules disabled in recommended.json @typescript-eslint takes over correctly.

But I've noticed some issues with the config. The order of extends is important if using another config, for example, airbnb. With order ["plugin:@typescript-eslint/recommended", "airbnb"], I get double errors, e.g. both camelcase and @typescript-eslint/camelcase. It's not a bug in the config and not something that can be fixed, but it's good to have a note of it to avoid needless frustration.
Here's a demo: https://github.com/markogresak/eslint-ts-aribnb-config-issue-example

@fatfatson
Copy link

facing the same problem.
expecting to have the ability for setting different rule set for ts and js files.

@kaicataldo
Copy link
Member

@fatfatson ESLint already supports this. Please see https://eslint.org/docs/user-guide/configuring#configuration-based-on-glob-patterns for more details.

@kaicataldo
Copy link
Member

Also of note: ESLint also now supports nested overrides and extends in overrides: eslint/eslint#11554 🎉

@bradzacher
Copy link
Member

This is actually huge!!!!
Awesome - we have to update the documentation with these changes.

@bradzacher bradzacher added the documentation Documentation ("docs") that needs adding/updating label Jun 17, 2019
@deskoh
Copy link

deskoh commented Jul 21, 2019

But I've noticed some issues with the config. The order of extends is important if using another config, for example, airbnb. With order ["plugin:@typescript-eslint/recommended", "airbnb"], I get double errors, e.g. both camelcase and @typescript-eslint/camelcase. It's not a bug in the config and not something that can be fixed, but it's good to have a note of it to avoid needless frustration.
Here's a demo: https://github.com/markogresak/eslint-ts-aribnb-config-issue-example

facing the same problem.
expecting to have the ability for setting different rule set for ts and js files.

@markogresak @fatfatson Turns out to have an equivalent Airbnb Typescript config is not straightforward, and yes, the ordering matters. See here for details. That was I am trying to achieve in my repo.

@danielamaia
Copy link

even tho the solution suggested by @markogresak is a good one, it would be even better if somehow we could just turn off all @typescript-eslint rules like
"rules": { "@typescript-eslint/*": "off" }.

It's not very maintainable having to manually add the rules to this list.

@kaicataldo
Copy link
Member

A potentially simpler way to do this would be to only turn on those rules for .ts(x) files using glob configuration. That way the rules are only on for TypeScript files and don’t need to be turned off for non-TypeScript files.

@bradzacher
Copy link
Member

bradzacher commented Sep 12, 2019

Woops, this issue fell through the cracks! It should have been closed a while ago.

As @kaicataldo mentioned, you can accomplish this easily using eslint's overrides functionality.

In eslint v6, there was as whole lot more support added to extends, and it now works really intuitively.

We're not going to bake in explicit file filters. In 2.0 we removed the instances of us doing this.
The rules that do not work on js code have this documented in their readmes, all other rules will work fine on js code.

@vuhuucuong
Copy link

vuhuucuong commented Sep 28, 2019

For anyone who wants a working .eslintrc. Here is my current config, I'm using glob patterns overrides for .ts and .tsx, and the default for .js, .jsx
I'm using eslint v6.3.0

{
  "env": { "browser": true, "es6": true, "node": true },
  "extends": ["eslint:recommended", "plugin:react/recommended"],
  "globals": { "Atomics": "readonly", "SharedArrayBuffer": "readonly" },
  "parser": "babel-eslint",
  "parserOptions": {
    "ecmaFeatures": { "jsx": true },
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "plugins": ["react"],
  "rules": {
    "indent": ["error", 2, { "SwitchCase": 1 }],
    "linebreak-style": ["error", "unix"],
    "quotes": ["error", "single"],
    "comma-dangle": ["error", "always-multiline"],
    "semi": ["error", "always"]
  },
  "settings": { "react": { "version": "detect" } },
  "overrides": [
    {
      "files": ["**/*.ts", "**/*.tsx"],
      "env": { "browser": true, "es6": true, "node": true },
      "extends": [
        "eslint:recommended",
        "plugin:react/recommended",
        "plugin:@typescript-eslint/eslint-recommended",
        "plugin:@typescript-eslint/recommended"
      ],
      "globals": { "Atomics": "readonly", "SharedArrayBuffer": "readonly" },
      "parser": "@typescript-eslint/parser",
      "parserOptions": {
        "ecmaFeatures": { "jsx": true },
        "ecmaVersion": 2018,
        "sourceType": "module",
        "project": "./tsconfig.json"
      },
      "plugins": ["react", "@typescript-eslint"],
      "rules": {
        "indent": ["error", 2, { "SwitchCase": 1 }],
        "linebreak-style": ["error", "unix"],
        "quotes": ["error", "single"],
        "comma-dangle": ["error", "always-multiline"],
        "@typescript-eslint/no-explicit-any": 0
      },
      "settings": { "react": { "version": "detect" } }
    }
  ]
}

itsjamie added a commit to video-dev/hls.js that referenced this issue Dec 20, 2019
This makes it so that TypeScript rules are applied as a override on the
glob '*.ts'.

Seems to be a best practice to avoid duplicate or meaningless rules
running on JS. See typescript-eslint/typescript-eslint#109 (comment).
@Thebarda
Copy link

Thebarda commented Jan 21, 2020

even tho the solution suggested by @markogresak is a good one, it would be even better if somehow we could just turn off all @typescript-eslint rules like
"rules": { "@typescript-eslint/*": "off" }.

It's not very maintainable having to manually add the rules to this list.

Does this syntax work on eslint@5.x.x ?

@murbanowicz
Copy link

even tho the solution suggested by @markogresak is a good one, it would be even better if somehow we could just turn off all @typescript-eslint rules like
"rules": { "@typescript-eslint/*": "off" }.
It's not very maintainable having to manually add the rules to this list.

Does this syntax work on eslint@5.x.x ?

Nope, this is just a wish how we would like it to work

@typescript-eslint typescript-eslint locked as resolved and limited conversation to collaborators Feb 21, 2020
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 package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin
Projects
None yet