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

New rule: disallow empty named blocks #2538

Closed
bradzacher opened this issue Aug 30, 2022 · 2 comments · Fixed by #2568
Closed

New rule: disallow empty named blocks #2538

bradzacher opened this issue Aug 30, 2022 · 2 comments · Fixed by #2568

Comments

@bradzacher
Copy link
Contributor

bradzacher commented Aug 30, 2022

Spinning this off of our discussion here #2473 (comment)

According to the ES6 spec an empty named import block import {} from 'mod' is valid syntax:

NamedImports :
    { }
    { ImportsList }
    { ImportsList , }

Because it's valid - all ESLint parsers allow it for value imports.

Parsers that handle type-only imports (flow/hermes/typescript/babel) also allow an empty named import block: import type {} from 'mod', (flow only) import typeof {} from 'mod'.

I suggest we build a new rule, no-empty-named-blocks, which bans these empty import blocks entirely.

Examples

✅ Valid

import 'mod';

import Default from 'mod';
import { Named } from 'mod';
import Default, { Named } from 'mod';
import * as Namespace from 'mod';

import type Default from 'mod';
import type { Named } from 'mod';
import type Default, { Named } from 'mod'; // note - invalid TS but valid Flow
import type * as Namespace from 'mod';     // note - valid TS but invalid Flow

// flow only
import typeof Default from 'mod';
import typeof { Named } from 'mod';
import typeof Default, { Named } from 'mod';

❌ Invalid

import {} from 'mod';
import Default, {} from 'mod';

import type {} from 'mod';
import type Default, {} from 'mod'; // note - invalid TS but valid Flow

// flow only
import typeof {} from 'mod';
import typeof Default, {} from 'mod';

Fixer

There are 3 cases for us to consider here:

First, an import with a default and an empty named block (either value, type, or typeof).
This can always be safely fixed to remove the empty block:

- import Default, {} from 'mod';
+ import Default from 'mod';

// flow only
- import type Default, {} from 'mod';
+ import type Default from 'mod';

// flow only
- import typeof Default, {} from 'mod';
+ import typeof Default from 'mod';

Second, a type-/typeof-only import with just an empty named block.
This can always be removed in its entirety as type-/typeof-only imports never have side-effects

- import type {} from 'mod';
+ 

Finally a value import with just an empty block.
This cannot be safely deleted because even without any specifiers the import will still trigger side-effects. Instead of an autofixer, we can use a suggestion fixer with two suggestions:

  1. Delete the import (fix by deleting the entire statement)
    - import {} from 'mod';
    + 
  2. Convert to a side-effect import (fix by deleting the {} from)
    - import {} from 'mod';
    + import 'mod';
@ljharb
Copy link
Member

ljharb commented Aug 30, 2022

That seems like a fine plan.

@guilhermelimak
Copy link
Contributor

Im working on this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

4 participants