Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork2.8k
feat(eslint-plugin): [strict-enums] new rule#4864
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
nx-cloudbot commentedApr 26, 2022 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Thanks for the PR,@Zamiell! typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community. The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately. Thanks again! 🙏Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently onhttps://opencollective.com/typescript-eslint. As a thank you, your profile/company logo will be added to our main README which receives thousands of unique visitorsper day. |
netlifybot commentedApr 26, 2022 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
✅ Deploy Preview fortypescript-eslint ready!
To edit notification comments on pull requests, go to yourNetlify site settings. |
codecovbot commentedApr 26, 2022 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Codecov Report
@@ Coverage Diff @@## main #4864 +/- ##==========================================- Coverage 94.25% 91.53% -2.73%========================================== Files 153 228 +75 Lines 8305 10856 +2551 Branches 2702 3351 +649 ==========================================+ Hits 7828 9937 +2109- Misses 263 637 +374- Partials 214 282 +68
Flags with carried forward coverage won't be shown.Click here to find out more.
|
Zamiell commentedApr 26, 2022 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
No idea why linting is failing in CI. It passes locally when I do |
Zamiell commentedApr 28, 2022 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I also found a bug with the Which means that the function signature of this method needs to be updated in the TypeScript repository. |
Uh oh!
There was an error while loading.Please reload this page.
also fixes for codebase
Zamiell commentedApr 29, 2022 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Some notes:
Needs to still be addressed:
The documentation here recommends using Here's a list of errors that I ignored:
This file has code that uses a reducer on an enum array, but with a starting value of Thus, the
This uses a complex type of
My first thought was to change this to The comment for the /** * This represents a string whose leading underscore have been escaped by adding extra leading underscores. * The shape of this brand is rather unique compared to others we've used. * Instead of just an intersection of a string and an object, it is that union-ed * with an intersection of void and an object. This makes it wholly incompatible * with a normal string (which is good, it cannot be misused on assignment or on usage), * while still being comparable with a normal string via === (also good) and castable from a string. */exporttype__String=(string&{__escapedIdentifier:void;})|(void&{__escapedIdentifier:void;})|InternalSymbolName; So I guess it's just weird and I should just put
Same as "no-implied-eval.ts".
Same as "no-implied-eval.ts".
Same as "no-implied-eval.ts". This monorepo is a good test case for finding bugs in the rule. For example, it caught a bug with variadic functions, which I didn't have a test case for originally. Still working on some of the other errors. |
Uh oh!
There was an error while loading.Please reload this page.
Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
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 is looking really good to me as it currently stands.
HOWEVER, I do see a large DevX problem in terms of "flags" enums. Now, flags enums are known to be unsafe.
Personally, I think in JS you should be using aSet
or array to store the a list of possible values, but I get why one might use a "flags" enum.:
- they're often used is for memory efficiency.
- for example - this is why TS went with a "flags" enum for its fields - saves a lot of memory across an entire project's ASTs.
- some would argue that there's a nice DevX to using bitwise-ops on flag enums.
- personally I think that they're a bit confusing to think about, though I can understand how they're familiar for someone comfortable with lower-level languages.
The point is though, this may be something we need to solve for in terms of devx.
Right now the answer is "too bad, so sad - union innumber
", but I don't think this is a good answer for those users because it destroys the type documentation for the usecases, for example:
Whilst I understand that in these cases it is "technically correct" for the type to benumber
, it's also not truly correct as it suggests things like "it's valid to pass 100 to this function", when it's not - because 100 satisfies neitherFoo.A
, norFoo.B
.
So with all that said, I think we need to determine a means for people to "opt out" of the rule for flags enums.
Perhaps it's something as simple as adding an option with an "allow flags naming pattern" similar totheno-unused-vars
rule'svarsIgnorePattern
option:
{"@typescript-eslint/strict-enums":["error",// treats any enum with name ending in "Flags" as a flags enum{"flagsEnumPattern":"Flags^"},],}
This way users can have the rule on for strict usecase, and opt-out (with a clear naming pattern) known "unsafe" usecases.
I know we'd certainly find value within this very codebase thinks to the TS flag enums!
WDYT?
@@ -65,7 +65,7 @@ class Reference { | |||
/** | |||
* In some cases, a reference may be a type, value or both a type and value reference. | |||
*/ | |||
readonly #referenceType: ReferenceTypeFlag; | |||
readonly #referenceType:number |ReferenceTypeFlag; |
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.
instead of unioning in number here, could we defineTypeOrNumber
as an enum member, and remove the bitwise operations on the enum?
*/ | ||
export function getTypeFlags(type: ts.Type): ts.TypeFlags { | ||
let flags: ts.TypeFlags = 0; | ||
export function getTypeFlags(type: ts.Type): number | ts.TypeFlags { |
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.
@JoshuaKGoldberg the point@Zamiell was making was that the code is written like this:
getTypeFlags(flag.one|flag.two| ...);
when could be written like this:
getTypeFlags(newSet([flag.one,flag.two, ...]);
Uh oh!
There was an error while loading.Please reload this page.
VariableDeclaration(node): void { | ||
for (const declaration of node.declarations) { |
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.
nitpick - we don't care about the declaration itself, just the declarators.
VariableDeclaration(node):void{ | |
for(constdeclarationofnode.declarations){ | |
VariableDeclarator(node):void{ |
This is good because it saves you manually iterating and it means your report will be cleaner.
I.e. instead of:
const x = 1,^^^^^^^^^^^^ y: Foo = 99;^^^^^^^^^^^^^^^^^
(where^
is the report underline)
you'll instead have:
const x = 1, y: Foo = 99; ^^^^^^^^^^^
Which is clearer and more accurate!
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Co-authored-by: Brad Zacher <brad.zacher@gmail.com>
Co-authored-by: Brad Zacher <brad.zacher@gmail.com>
Co-authored-by: Brad Zacher <brad.zacher@gmail.com>
Zamiell commentedMay 31, 2022 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There are branch conflicts in thre README.md files.
|
Also, after Brad's updates, I get the following errors when building:
Anyone know why that is? I'm unable to work on the branch until that is resolved. |
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 this is looking good so far.
I'm happy if we want to get this in and out to people to play with.
Fix the merge conflicts and we can get to it!
## Banned Patterns | ||
This rule bans: | ||
1. Enum incrementing/decrementing - `incorrectIncrement` | ||
1. Mismatched enum declarations/assignments - `mismatchedAssignment` | ||
1. Mismatched enum comparisons - `mismatchedComparison` | ||
1. Mismatched enum function arguments - `mismatchedFunctionArgument` |
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 is just a less-verbose duplicate of "Error Information" below - so let's remove this.
Brad can you respond to my messages on May 31st? |
bradzacher commentedAug 7, 2022 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@Zamiell - both At the time the "canonical" table was the former (root readme), and the latter was added as part of the website build. However the rules table is now no longer generated in source files - instead they are generated as part of the website build. |
👋@Zamiell, just checking in - do you still have time to work on this? And if so, are there still open questions you're waiting on answers to? |
Closing this PR as it's been stale for a few months without activity. Feel free to reopen@Zamiell if you have time - but no worries if not! If anybody wants to drive it forward, please do post your own PR - and if you use this as a start, consider adding |
Moving to#6091. I want these checks to exist 😄 |
Uh oh!
There was an error while loading.Please reload this page.
PR Checklist
Overview
Makes working with enums not suck. See thedocs that I wrote for the rule.
This PR is a draft; I am still working on it but I will start a PR for now in case anyone wants to give me early feedback.