ESLint rule to require one variable declaration statement per line? - eslint

Is there an eslint (or typescript-eslint) rule to require each var/let/const statement appear on its own line? I've tried one-var, one-var-declaration-per-line, and max-statements-per-line. From my experiments, max-statements-per-line is too aggressive, targeting some single-line patterns we commonly use. The other two rules don't correctly catch multiple var statements on one line. Is there another rule or configuration I'm overlooking?
Specific example:
let foo: string; let bar: string;
let blah = function blah() { console.log('woot'); };
.eslintrc:
{
"rules": {
// "max-statements-per-line": "error",
"one-var": [ "error", "never" ],
"one-var-declaration-per-line": [ "error", "always" ]
}
}
No errors reported given this config. Uncommenting the max-statements-per-line rule flags both lines. I'd like a ruleset that flags the first line, but allows the second.

The rules you list only apply to single statements (i.e. things where it's invalid to put a ; in the middle). What you have there are multiple statements on a single line. It would be similar if you did:
console.log('foo'); console.log('bar');
You can prohibit any lines with 2 statements using:
"max-statements-per-line": ["error", { "max": 1 }],
Tip: There are a ton of these types of issues that are all covered by the prettier formatter, and you can integrate it into eslint so that anything it sees as improperly formatted is also a linting error. This issue, all types of spacing/indention issues, wrappable lines, and more all come "for free".
extending plugin:prettier/recommended disables a bunch of other rules that would normally conflict, so you can leave out a lot of things from the eslint config like quotes, semi, arrow-parens, etc. because they'll be disabled anyway.
{
"parser": "#typescript-eslint/parser",
"plugins": [
"#typescript-eslint/eslint-plugin",
"#typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:#typescript-eslint/recommended",
// prettier configs must come last to disable conflicting rules!
"prettier",
"plugin:prettier/recommended"
]
"rules": {
// ...
}
}

Related

NX Error for Relative Imports within the Same Project

I'm getting an error when using TS aliased paths within the same project: Projects should use relative imports to import from other files within the same project
I don't want this behavior. Any idea how to disable?
I tried playing with the #nrwl/nx/enforce-module-boundaries option, but it has almost no documentation around its options
// NX doesn't like this line which uses a path to a file within the
// same NX project. It wants me to use relative pathing, which I
// don't want to use
import { fooHandler } from '#handlers/foo';
Had to look through the npm package, but found it by searching for the error text. You can disable it like this from inside of your .eslintrc.json settings:
{
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {
"#nrwl/nx/enforce-module-boundaries": [
"error",
// This is the part you need to add
{ "allowCircularSelfDependency": true }
]
}
}
]
}
For those who are coming here without this getting resolved. (nx monorepo usage)
For lint error:
Projects should use relative imports to import from other files within the same project - eslint rule #nrwl/nx/enforce-module-boundaries fails
Add "allowCircularSelfDependency": true.
"#nrwl/nx/enforce-module-boundaries": [
"error",
{
"allowCircularSelfDependency": true, -> This may solve the lint error.
"allow": ["#account/**"], -> // White list the lint error.
...
}
Whitelist the folders: Add "allow": [#foldername]
"#nrwl/nx/enforce-module-boundaries": [
"error",
{
"allow": ["#account/**"], -> // White list the lint error.
...
}
That should fix it.

ESLint conflicts with eslint-plugin-import and typescript-eslint

I want to include the rule no-unpublished-import from eslint-plugin-node, however, it is conflicting with my current .eslintrc because I am using typescript-eslint and eslint-import-resolver-typescript.
It is my current configuration:
{
"parser": "#typescript-eslint/parser", // Specifies the ESLint parser
"extends": [
"airbnb-base",
"plugin:#typescript-eslint/recommended", // Uses the recommended rules from the #typescript-eslint/eslint-plugin
"prettier", // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array
"prettier/#typescript-eslint" // Uses eslint-config-prettier to disable ESLint rules from #typescript-eslint/eslint-plugin that would conflict with prettier
],
"parserOptions": {
"project": "./tsconfig.json",
"ecmaVersion": 6, // Allows for the parsing of modern ECMAScript features
"sourceType": "module" // Allows for the use of imports
},
"rules": {
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".ts"]
},
// use <root>/tsconfig.json
"typescript": {
"alwaysTryTypes": true // always try to resolve types under `<root>#types` directory even it doesn't contain any source code, like `#types/unist`
}
}
},
"root": true
}
The code compiles correctly, however, if I add to the extends option the plugin:node/recommended the compilation process will fail:
1:1 error Import and export declarations are not supported yet node/no-unsupported-features/es-syntax
1:43 error "express" is not found node/no-missing-import
2:1 error Import and export declarations are not supported yet node/no-unsupported-features/es-syntax
My package.json includes the node": ">=12.0.0. Also, this rule should be ignored because I am using typescript. On the other hand, I am just exporting types from express because the module don't use it.
According to this issue the conflict should be resolved by eslint-plugin-node.
How can I accomplish the merge of both plugins? Do I have to go disabling rules one by one?
UPDATED:
It seems it was asked in this issue on the eslint-plugin-node repository. It works for no-unsupported-features and no-missing-import, however, it is still failing with the import definition of express with no-extraneous-import.
UPDATED 2:
It seems eslint-plugin-node is working on a enhancement to accomplish it. Issue here
Firstly, you have to add the option tryExtension to include TS files:
"settings": {
"node": {
"tryExtensions": [".js", ".json", ".node", ".ts", ".d.ts"]
},
To solve the no-unsupported-features/es-syntax, according to this issue about adding information to works with TypeScript, if you work with transpilers you will have to ignore it under rules:
"node/no-unsupported-features/es-syntax": ["error", { "ignores": ["modules"] }],
On the other hand, use just types and not the code is not supported yet by the eslint-plugin-node. They are working on a enhancement to solve it. However,, to solve the no-missing-import, you have to add to the resolvePath the node_modules/#types:
"node": {
"resolvePaths": ["node_modules/#types"],
"tryExtensions": [".js", ".json", ".node", ".ts", ".d.ts"]
},
Even so, it will generate a no-extraneous-import because it doesn't detect the module, because it is just a type. Meanwhile they are working on this enhancement, you can use allowModules under that rule for workaround:
"node/no-extraneous-import": ["error", {
"allowModules": ["express"]
}]

ESLint - Override rules from eslint-plugin-prettier

I am using ESLint with the prettier plugin and configuration:
// eslintrc.js
extends: [
`eslint:recommended`,
`plugin:react/recommended`,
`plugin:#typescript-eslint/recommended`,
`plugin:prettier/recommended`,
`prettier/react`,
`prettier/#typescript-eslint`
]
This works great, but I would like to disable a certain prettier rule, which is removing "unneeded" parentheses (removing them actually breaks my code):
// Replace `(state.counter)` with `state.counter` eslint(prettier/prettier)
return <div>{(state.counter)}</div>
As you can see from the message above, it doesn't state which rule exactly is causing this behavior and therefore I don't know which one to override.
I have tried to override all rules found in eslint-prettier-config, but nothing worked and I don't want to keep using // eslint-disable-next-line prettier/prettier.
Prettier is not so configurable. You can try configuration they have: https://prettier.io/docs/en/configuration.html
Put .prettierrc file, or eslint config like this:
{
rules: {
'prettier/prettier': [
'error',
{
trailingComma: 'all',
tabWidth: 2,
semi: false,
singleQuote: true,
bracketSpacing: true,
eslintIntegration: true,
printWidth: 120,
},
],
}
}
It is not currently possible to disable that specific rule from prettier through configuration, but to override rules in eslint that come from the extends block, you can either write in the rule like this:
"rules": {
"prettier/prettier": "off"
"#typescript-eslint/no-use-before-define": [
"error",
{ "functions": false, "variables": true, "classes": true },
],
}
Or to only override it for a specific file pattern you can override it in the overrides block.
"overrides": [
{
"files": ["*.html"],
"rules": {
"prettier/prettier": "off",
"#typescript-eslint/unbound-method": "off"
}
}
]
Here I am showing both the config you were looking for, and an inherited rule from a nested package to show future visitors how to do it.

Turn off error for console.log on my eslint

I'm trying to turn off lint warning for my eslint at VS code.
My code is contains.
console.log('blabla..');
eslint said as below.
error Unexpected console statement no-console
Even though already add no-restricted-syntax at my .eslintrc.json, no fixed.
Here is my .eslintrc.json
{
"env": {
"es6": true,
"node": true,
"amd": true,
"mocha": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 2017,
"sourceType": "module"
},
"rules": {
"linebreak-style": [
"error",
"windows"
],
"no-restricted-syntax": [
"error",
{
"selector": "CallExpression[callee.object.name='console'][callee.property.name=/^(log|warn|error|info|trace)$/]",
"message": "Unexpected property on console object was called"
}
]
}
}
What did I mistake?
Allowing the console.log to stay in code is requiring a separate rule.
You need to add 'no-console' statement to your eslint config rules.
Like so:
rules: {
"no-console": 0
}
A better practice is to warn you about all the console.log in your code, like so:
rules: {
"no-console": 1
}
I followed the advice of Elad and went into the package.json to add the rule of "no-console": 0 and at first it didn't seem like it worked but this is because I needed to restart the development server. If it seems like it's not working, make sure you restart the development server because if you change anything in the package-json, you have to restart your server.
You can add // eslint-disable-line if you need to ignore a specific (or multiple) line

eslint Failures in Travis CI, but not locally

I have a GitHub project that has passed Travis CI. Upon creating a pull request for a new feature, Travis CI fails both pr and push due to two eslint errors:
/home/travis/build/enove/Thriver/packages/thriver-accounts/lib/accounts.js
121:5 error Strings must use singlequote quotes
122:5 error Strings must use singlequote quotes
Lines 119 through 122 of accounts.js are as follows:
119: return `Hello ${user.profile.firstname}!\n\n` +
120: `To verify your account email, simply click the link below.\n\n${url}\n\n` +
121: `If you weren't expecting this email, simply delete it.\n\n` +
122: `Thanks!\n\nAll of us at WCASA`;
The commit did not even change accounts.js, and a local eslint passes without error. I checked and verified that the versions of node, npm, and meteor are the same locally as they are in Travis CI.
The Travis CI configuration is as follows:
{
"sudo": "required",
"language": "node_js",
"node_js": "4.1.1",
"before_install": [
"curl -L https://git.io/ejPSng | /bin/sh"
],
"env": "CXX=g++-4.8",
"addons": {
"apt": {
"sources": [
"ubuntu-toolchain-r-test"
],
"packages": [
"g++-4.8"
]
}
},
"services": "mongodb",
"script": [
"meteor npm run lint"
],
"group": "stable",
"dist": "precise",
"os": "linux"
}
The .eslintrc is as follows:
{
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 6,
"ecmaFeatures": {
"impliedStrict": true
}
},
"env": {
"browser": true,
"node": true,
"mongo": true,
"meteor": true
},
"extends": [
"airbnb"
//"plugin:meteor/recommended"
],
"globals": {
"Thriver": true,
"SimpleSchema": true,
"Marked": true,
"SHA256": true,
"google": true,
"geoXML3": true,
"AutoForm": true,
"details_shim": true
},
"rules": {
"no-underscore-dangle": 0,
"new-cap": 0
}
}
This has happened before in a different file and I "resolved" the issue by having eslint ignore the line. But I can't do that for every mystery issue. Any advice?
http://eslint.org/docs/rules/quotes
This is most likely the fix to your problem.
JavaScript allows you to define strings in one of three ways: double quotes, single quotes, and backticks (as of ECMAScript 6). For example:
/*eslint-env es6*/
var double = "double";
var single = 'single';
var backtick = `backtick`; // ES6 only
The choice of how to define strings in a codebase is a stylistic one outside of template literals (which allow embedded of expressions to be interpreted). Many codebases require strings to be defined in a consistent manner.
I would try setting one of these rules and running the tests again.
Let me know if this does not fix your problem!
I still have no idea how eslint was passing locally. Perhaps I was behind in eslint or airbnb version. However, I realized that the lines really did need to be corrected. The bottom two lines of code should not use back ticks because there aren't any variables in those strings.
119: return `Hello ${user.profile.firstname}!\n\n` +
120: `To verify your account email, simply click the link below.\n\n${url}\n\n` +
121: 'If you weren\'t expecting this email, simply delete it.\n\n' +
122: 'Thanks!\n\nAll of us at WCASA';
Eslint is a lot happier with a concatenated string of different styles than a consistent one where not every segment contains a variable.

Resources