-
Notifications
You must be signed in to change notification settings - Fork 531
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
New ESLint config #9748
New ESLint config #9748
Conversation
8da303a
to
f50d8b1
Compare
c5bdf23
to
2a9ecd8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm maybe halfway through default.json, submitting some initial feedback. Couple broader feedback items:
- This PR is making two main changes (1) structure and (2) actual rule changes. It would be easier to review and understand the changes if this were split into two PRs, first just restructuring but changing no policy, and second being the opinionated policy changes.
- I want to be super pedantic about formatting, I've spent too much time giving formatting feedback in PRs when the rules have not been enabled, and I'm sure the recipients of that feedback would have loved for eslint:fix to work :-P. If/when tsfmt eventually becomes part of the build pipeline then maybe we move the responsibility, but in the shorter term we should keep these as build failures so our code doesn't decay.
], | ||
"@typescript-eslint/dot-notation": [ | ||
"error" | ||
], | ||
"@typescript-eslint/explicit-function-return-type": [ | ||
"@typescript-eslint/eol-last": [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like eols to be enforced, plus can easily autofix -- would prefer error here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EOL enforcement is handled by the editorconfig plugin.
], | ||
"@typescript-eslint/indent": [ | ||
"off" | ||
], | ||
"@typescript-eslint/interface-name-prefix": [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interface-name-prefix is probably a good rule to have turned on (I thought it had been on?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has never been on AFAIK. We don't seem to follow a naming standard today for interfaces. Are you suggesting we adopt one?
@@ -162,13 +180,22 @@ | |||
"off" | |||
], | |||
"@typescript-eslint/no-invalid-this": [ | |||
"off" | |||
"error" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed everything except for the unicorn rules now
], | ||
"no-undef": [ | ||
"off" | ||
], | ||
"no-undef-init": [ | ||
"error" | ||
], | ||
"no-underscore-dangle": [ | ||
"off" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use dangling underscores quite a bit, want to make sure this is still permitted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where you see a rule that was previously off that is now removed completely, it means that the rule was always off by default, and the previous config explicitly turned it off unnecessarily.
I see how confusing this is.
@@ -734,17 +757,14 @@ | |||
"error" | |||
], | |||
"no-void": [ | |||
"off" | |||
"error" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should continue to permit void probably.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel intimidated by the docs: https://eslint.org/docs/rules/no-void
I think that anyone who feels confident enough to use void can disable the rule with a comment. It doesn't seem like something most TS devs would need.
@@ -2,6 +2,7 @@ | |||
"env": { | |||
"browser": true, | |||
"es6": true, | |||
"jest/globals": true, | |||
"node": true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how does this work with isomorphic packages trying to directly use node types? or is that fine since the work to move to webpack 5 is underway?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Ideally we'd have individual configs for every package with the minimal env for each... but I also think that we'll need other mechanisms to help enforce browser-compatible packages, so maybe this is ok.
"error" | ||
], | ||
"unicorn/no-nested-ternary": [ | ||
"error" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not exactly sure how unicorn/no-nested-ternary handles multiline ternary nesting, but seems OK for single line based on the documentation. I guess we'll see how it plays out in the repo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to do pretty well on multi line too. I find it aids readability, but YMMV.
"error" | ||
], | ||
"unicorn/no-new-array": [ | ||
"error" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love this no-new-array rule, just heads up it might hit issues in some of our packages
"unicorn/no-new-buffer": [ | ||
"error" | ||
], | ||
"unicorn/no-null": [ | ||
"error" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like disallowing null, but I think we have multiple rules for this? Wondering if we need all of them long-term.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They pick up different cases, and I don't know why. My working theory is that the rushstack one is too conservative (doesn't detect cases I would expect it to) but the unicorn one doesn't know TypeScript. Let's see how they play out.
"error" | ||
], | ||
"unicorn/prevent-abbreviations": [ | ||
"off" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prevent-abbreviations seems interesting -- agree with disabling to start but might be nice to experiment with enabling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You refer to experimenting... I'm finding it difficult to experiment with our rules. I think if we want to experiment we should do it on a project by project basis, enabling them in the project overrides. But I never know which projects are interesting to experiment with what rules. 😄
I think this one will need a lot of manual tweaking to cross the useful/annoying threshold.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I was thinking more about just private experimentation to understand the rule better and see what works well before trying to enable it anywhere.
@ChumpChief @heliocliu I just pushed an update that incorporates a lot of your feedback. Details are in the PR description. |
], | ||
"@typescript-eslint/no-unsafe-return": [ | ||
"error" | ||
], | ||
"@typescript-eslint/no-unused-expressions": [ | ||
"error" | ||
"warn" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should keep errors on no-unused-expressions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't remember why I changed this, so I'll change it back, remember why I lowered it 😆 then RAGING DEBATE can ensue.
I converted this to a draft since I don't intend to merge as-is. |
Part of #9501.
Update 2022-04-20
After discussing more with @ChumpChief, I am preparing additional PRs to apply fixes for some of the new rules before merging this and publishing a prerelease. This will ease the integration of the new config.
Update 2022-04-12
The latest PR contains the following changes based on feedback in the review:
Changed to Error
Changed to Warn
Disabled
Other changes
This PR updates our shared lint config by consolidating the three separate configs into a single config,
shared-config.js
. This config is much stricter than the current minimal config. Every rule that we override is listed alphabetically in the config, along with a brief summary of the intention behind the rule.A plea
Choosing default lint rules is inherently an opinionated exercise. In the absence of feedback, my opinions regarding lint defaults will become the "law of the land," and that should scare you as much as it does me. 😄 Please let your own opinions be heard!
All that said, after this is merged, I'll follow up with another PR to apply the config across the repo. When that happens, you'll have another opportunity to weigh in on the rules. But it's easier to make changes now.
How to review
To ease this review, I suggest reviewing default.json, which is the diff of the final applied config, taking into account all our plugins, parent configs, etc. That is easier than looking at the config file itself since that file is all new.
Q and A
How did you decide what should be a warning vs. an error?
Practically speaking, the difference between an ESLint error and a warning is that errors fail the build, while warnings don't. The default is that everything is an error, and I generally feel that rules that aren't enforced by build breaks aren't useful. However, there are two situations where I feel a warning is better.
First, if the rule is likely to have a lot of offenders in our code, or if fixing the issues is complex and warrants careful code review, then warning is appropriate because it lets us adopt the new config without temporarily disabling rules and then forgetting to ever turn them off again. Warnings have a tendency to get fixed because eventually someone gets annoyed, 😄 Large-scale lint changes are hard to review because there are often so many changes, so warnings enable us to have more targeted changes that are better reviewed. An example of this kind of rule:
Second, if the rule is more about formatting or style than code correctness, and I was worried about it being too strict or too controversial, I used warnings. Examples of these kinds of rules:
These are all opinionated decisions, and I may have been more arbitrary than the above describes. Let me know where you disagree.
How did you decide what formatting rules to enable?
I prefer to focus linting on finding code issues, either in logic or style. Formatting is a different task, better left to dedicated formatting tools like tsfmt, which is what VS Code uses internally when you format a file. Many lint rules regarding formatting require a lot of connfiguration to work as we want, but our "style guide" is pretty simple -- whatever VS Code produces is the "correct" formatting. Configuring lint rules to do what VS Code "just does" makes me sad, which is why we have a tsfmt task for most projects. It isn't running as part of the build (yet), so some formatting-related lint rules are enabled, but they should be the exception.How do we apply this config to projects with lots of offenses?
You can disable rules as needed to unblock yourself. You should always prefer line-level disables. If there is a contiguous block of the same offense, then using an disable/enable block comment is acceptable. Project-level overrides (these live in
.eslintrc.js
) should not be used. They're too easy to forget to clean up. The exception to this is test projects, which might have legitimate reasons to adjust rules at the project level.