eslint-plugin-import icon indicating copy to clipboard operation
eslint-plugin-import copied to clipboard

[no-duplicates] prefer-inline breaks unassigned and top-level type imports

Open oleasteo opened this issue 11 months ago • 4 comments

"import/no-duplicates": ["error", { "prefer-inline": true }],

Will detect an error in the following typescript code:

import type { X } from "xyz";

import "xyz";

// [...]

It will auto-fix by removing the import "xyz"; statement. This is not the desired behavior. I would expect it to stay as is.

Merry Christmas 🎄

oleasteo avatar Dec 23 '24 15:12 oleasteo

I would expect prefer-inline: true to require import { type X } from 'xyz'; for the first line; does it not?

For the second line, I assume this is because xyz is side-effecting, and you want to ensure type-stripping leaves the evaluation intact?

ljharb avatar Dec 23 '24 17:12 ljharb

It does not require import { type X } from 'xyz';. It does prefer mixed imports over one import for types and a separate one for named runtime.

import { abc } from "xyz";
import type { X } from "xyz";

would be changed to

import { abc, type X } from "xyz";

but if no named runtime imports exist, it won't touch import type ... declarations (which is consistent with typescript verbatimModuleSyntax).

For the second line, I assume this is because xyz is side-effecting, and you want to ensure type-stripping leaves the evaluation intact?

Precisely.


FYI, the style I'm aiming for with all the relevant rules:

  1. make sure type-only use is type-imported (@typescript-eslint/consistent-type-imports)
  2. avoid duplicate imports, including mixed type/runtime declarations (import/no-duplicates { "prefer-inline": true })
  3. if only type imports exist, make it top-level import type {...} (@typescript-eslint/no-import-type-side-effects)
    • this allows verbatimModuleSyntax to strip type-only imports
  4. don't touch import "..." statements at all; they're meant to explicitly define side-effect imports
    • I would prefer to automatically group them to the start / end of the import block, unless eslint-disabled per file, but that's a different beast

Personally, I think this is a perfect solution to clean imports. Especially, if combined with import/order to group import type separately.

oleasteo avatar Dec 24 '24 11:12 oleasteo

I would expect prefer-inline: true to require import { type X } from 'xyz'; for the first line; does it not?

It does not, unfortunately.

This:

import { type A } from 'foo';

import 'foo';

Is turned into:

import 'foo';

todor-a avatar Jun 23 '25 20:06 todor-a

I decided to give it a go in https://github.com/import-js/eslint-plugin-import/pull/3194.

todor-a avatar Jun 25 '25 18:06 todor-a