Skip to content

feat(eslint-plugin): [no-unsafe-enum-assignment] add rule #6091

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

Closed

Conversation

JoshuaKGoldberg
Copy link
Member

@JoshuaKGoldberg JoshuaKGoldberg commented Nov 25, 2022

PR Checklist

Overview

Adds a new no-unsafe-enum-assignment rules that prevents assigning literals to enum values.

no-unsafe-enum-comparison was split out to #6107.

Co-authored-by: @Zamiell

Zamiell added 30 commits April 27, 2022 13:53
also fixes for codebase
@bradzacher bradzacher added the awaiting response Issues waiting for a reply from the OP or another party label Dec 16, 2022
@JoshuaKGoldberg JoshuaKGoldberg requested review from bradzacher and removed request for Zamiell December 16, 2022 17:57
@JoshuaKGoldberg JoshuaKGoldberg removed the awaiting response Issues waiting for a reply from the OP or another party label Jan 10, 2023
@bradzacher
Copy link
Member

bradzacher commented Jan 30, 2023

Additional cases that this rule should handle:

  • class properties
    class F {
      prop: Fruit = 1;
    }
    • There's also cases like this:
      interface F { prop: Fruit; }
      class Foo implements F {
        prop = 1;
      }
  • object properties
    const x = { prop: 1 } as { prop: Fruit ))
  • assertions in general?
    const x = 1 as Fruit;
    const y = <Fruit>1;
  • JSX attributes
    type Props = { prop: Fruit };
    declare function Component(props: Props): JSX.Element;
    (<Component prop={1} />);
  • return statements
    function x(): Fruit {
      return 1;
    }
  • computed member expression properties
    declare const foo: { [k in Fruit]: string };
    foo[0];
    foo?.[0];
    
    declare const bar: { [Fruit.Apple]: string };
    bar[0];
    bar?.[0];

Edge cases to think about:

declare function fn(arg: Fruit): void;
fn(...[1]);

const x = [1, Fruit.Apple, 2] as const;
const y: readonly Fruit[] = x;

interface Foo<T extends Fruit> { prop: T; }
export const clazz: Foo<Fruit> = class WTF {
    static prop = 1;
}

@bradzacher bradzacher added the awaiting response Issues waiting for a reply from the OP or another party label Jan 30, 2023
@JoshuaKGoldberg
Copy link
Member Author

Yeah, there are a lot of cases to handle here. Basically any identifier and literal has to be checked - including array literals and parameters to generic functions!

I don't have the time to work on this rule given other, more important features to work on. So I'm going to close this PR. If anybody else wants to pick it up, please do!

Note that the code will likely need to be refactored a good bit to support all the new cases.

@JoshuaKGoldberg JoshuaKGoldberg deleted the strict-enums branch February 4, 2023 21:23
@JoshuaKGoldberg JoshuaKGoldberg restored the strict-enums branch February 4, 2023 21:23
@bradzacher
Copy link
Member

I wonder @JoshuaKGoldberg - do you think this should be built directly into our no-unsafe-* rules, rather than being their own rule.

The reason I originally split up the rules into a set was to isolate the logic for checking assignments in each case to reduce the overall maintenance complexity.
So those rules already contain much of the logic required by this rule in terms of getting contextual types and checking generics.

They don't currently do some of the checks I've listed (like checking when {prop: any} is assigned to {prop: string}), but at least there would be parity.

WDYT? Do we refactor to reuse logic or build into those rules?

@JoshuaKGoldberg
Copy link
Member Author

Hmmmmm, my gut reaction is that I'd rather extract those things out into shared utilities. +1 to reusing the logic for sure. Enums really aren't the same use case as any safety. I also had to reimplement a bunch of them in TypeStat and that was a huge pain.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
awaiting response Issues waiting for a reply from the OP or another party enhancement: new plugin rule New rule request for eslint-plugin
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants