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

[consistent-type-imports] add option to autofix to a single type import #2769

Closed
TwitchBronBron opened this issue Nov 16, 2020 · 18 comments
Closed
Labels
accepting prs Go ahead, send a pull request that resolves this issue enhancement: plugin rule option New rule option for an existing eslint-plugin rule package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin

Comments

@TwitchBronBron
Copy link

TwitchBronBron commented Nov 16, 2020

I'd like to propose a third option for the consistent-type-imports rule's prefer property. It currently has two options for prefer: type-imports and no-type-imports. However, it would be very useful to have a third option:

  • type-imports-combine: enforce all type-only imports to be import type except when there's already a concrete import from that same file, in which case prefer to combine the imports into a single statement.

Here's an example:

Logger.ts

export class Logger implements ILogger {
    log(message: string) {
        console.log(message);
    }
}
export interface ILogger {
    log(message: string);
}

main.ts

prefer: 'type-imports'

import { Logger } from './Logger';
import type { ILogger} from './Logger';
import type { SomeInterface } from './SomeInterface';

prefer: 'no-type-imports'

import { ILogger, Logger } from './Logger';
import { SomeInterface } from './SomeInterface';

New proposal:

prefer: 'type-imports-combine'

import { type ILogger, Logger } from './Logger';
import type { SomeInterface } from './SomeInterface';
@TwitchBronBron TwitchBronBron added package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for maintainers to take a look labels Nov 16, 2020
@bradzacher bradzacher added enhancement: plugin rule option New rule option for an existing eslint-plugin rule and removed triage Waiting for maintainers to take a look labels Nov 17, 2020
@bradzacher
Copy link
Member

Happy to accept a PR

@olee
Copy link

olee commented Dec 5, 2020

Please please please do this!
Just enabled the rule for me as well just to find out it would split all the mixed import lines into multiple which makes this unusable for me.
Maybe I will also try to do a PR for this one, but I'm not sure I can do it.

olee added a commit to olee/typescript-eslint that referenced this issue Dec 5, 2020
This ads a new mode called "" for consistent-type-imports rule which will only trigger, if all imports of an import declaration are type only imports.

References typescript-eslint#2769
olee added a commit to olee/typescript-eslint that referenced this issue Dec 5, 2020
This ads a new mode called "type-imports-mixed" for consistent-type-imports rule which will only trigger, if all imports of an import declaration are type only imports.

References typescript-eslint#2769
@olee
Copy link

olee commented Dec 5, 2020

Ok I think I got it working - this should prevent the rule from triggering when there are mixed imports

olee added a commit to olee/typescript-eslint that referenced this issue Dec 5, 2020
This ads a new mode called "type-imports-mixed" for consistent-type-imports rule which will only trigger, if all imports of an import declaration are type only imports.

References typescript-eslint#2769
olee added a commit to olee/typescript-eslint that referenced this issue Dec 6, 2020
This ads a new mode called "type-imports-mixed" for consistent-type-imports rule which will only trigger, if all imports of an import declaration are type only imports.

References typescript-eslint#2769
@marcus-sa

This comment has been minimized.

@bradzacher
Copy link
Member

With any issue in opened in this project - it either has a visible progress in the form of an attached PR, or it has no progress.

We are a community run project. The volunteer maintainers spend most of their time triaging issues and reviewing PRs. This means that most issues will not progress unless a member of the community steps up and champions it.

If this issue is important to you - consider being that champion.

If not - please just subscribe to the issue and wait patiently.
Commenting asking for status updates does not bump issue priority in any way and just serves to spam everyone subscribed to the issue.

@JoshuaKGoldberg JoshuaKGoldberg added the accepting prs Go ahead, send a pull request that resolves this issue label Oct 25, 2021
@merrywhether
Copy link
Contributor

merrywhether commented Dec 6, 2021

With the release of TS 4.5, it seems like updating the fixer to use inline type annotations (skipped in #4237 due to complexity) addresses the underlying issue here as you'd get:

import { type ILogger, Logger } from './Logger';
import { type SomeInterface } from './SomeInterface';

@bradzacher
Copy link
Member

yup - with 4.5 we can now autofix to use inline types to combine the imports.
the fixer code is super complicated which is why I skipped it. There's a lot of branches in the fixer, and the code isn't the cleanest - so it's a non-trivial amount of work to build such an option.

It's worth noting that with support for 4.5's inline type qualifier in #4237 - we don't explicitly need fixer support in the rule. Instead a rule like import/no-duplicates could be enhanced to merge imports as inline imports.

Eg the fix would be

// original
import { ILogger, Logger } from './Logger';

// @typescript-eslint/consistent-type-imports
import type { ILogger } from './Logger';
import { Logger } from './Logger';

// import/no-duplicates
import { type ILogger, Logger] from './Logger';

OFC it'd be great if we had support in our rule to cut-out the middleman.

@merrywhether
Copy link
Contributor

Should there be a new issue to reflect that work and replace this one? I'm looking at the fixer logic now to see just how hard the augmentation would be.

@bradzacher
Copy link
Member

no we can keep this one - i've update this issue to match.
it was almost correct already anyways!

@merrywhether
Copy link
Contributor

Should it be

import type { SomeInterface } from './SomeInterface';

like the description or

import { type SomeInterface } from './SomeInterface';

The second version is more accommodating to additional imports from the same source with fewer changes necessary?

@bradzacher
Copy link
Member

bradzacher commented Dec 6, 2021

IMO the former as it allows tools to ahead-of-time optimise the import away instead of having to interrogate all the imports to determine if it includes a type-aware import.

eg compilers can do

- import type { SomeInterface } from './SomeInterface';

instead of

// (1)
  import {
-   type SomeInterface
  } from './SomeInterface';
// (2)
- import {} from './SomeInterface';

additionally tools that analyse imports (lint rules etc) can understand the file's dependencies easier for the same reason.

@ocket8888
Copy link

ocket8888 commented Jan 20, 2022

IMO, it depends on the imports themselves. Currently I have a rule enforcing no duplicate imports, which means I can't use the consistent-type-imports rule, because many packages have mixed types and values. For instance, if a package "src/foo" exports the type Foo and the value Bar, using consistent-type-imports would mean that any other module that wants to import both would need to import them like:

import type { Foo } from "src/foo";
import { Bar } from "src/foo";

which duplicates imports. What I'd like to be able to do - independent of supporting inline type - is

import { Foo, Bar } from "src/foo";

because it recognizes that at least one import is a value so it cannot be an import type.

But to get back on-topic, the rule should, IMO prefer

import type { Foo } from "src/foo";

over

import { type Foo } from "src/foo";

because all imports are types, but should not raise an issue (optionally?) if one has

import { Bar, type Foo } from "src/foo";

because at least one import is not a type.

Also, this probably isn't the appropriate place to mention this, but Angular uses type annotations for dependency injection, so even if FooService is only used as a type, it needs to be imported as a value for the compiler's sake, which consistent-type-imports doesn't (and probably can't) recognize.

@bradzacher
Copy link
Member

Currently I have a rule enforcing no duplicate imports, which means I can't use the consistent-type-imports rule, because many packages have mixed types and values

Why not? Why can't your duplicate import rule handle this and fix it appropriately?
Lint rules are purposely isolated and unaware of one another and aren't expected to output fixes that won't report in another rule.
For example - if a rule fixes a class method to a class property - it doesn't need to insert a ; with the fix as it can assume the user will have a rule to fix that separately.

If you're using ESLint's core no-duplicate-imports rule, then you're going to be in for a bad time - you should look to a decent version like import/no-duplicates (#4238)


Also, this probably isn't the appropriate place to mention this, but Angular uses type annotations for dependency injection, so even if FooService is only used as a type, it needs to be imported as a value for the compiler's sake, which consistent-type-imports doesn't (and probably can't) recognize.

This is supported - if you use type-aware linting.
If you don't use type-aware linting then our analysis tools can't determine if you've got all the directive options turned on or not.
But that is very off topic for this issue.

@ocket8888

This comment was marked as off-topic.

@bradzacher

This comment was marked as off-topic.

@shpakkdv

This comment was marked as spam.

@bradzacher
Copy link
Member

With any issue in opened in this project - it either has a visible progress in the form of an attached PR, or it has no progress.

We are a community run project. The volunteer maintainers spend most of their time triaging issues and reviewing PRs. This means that most issues will not progress unless a member of the community steps up and champions it.

If this issue is important to you - consider being that champion.

If not - please just subscribe to the issue and wait patiently.
Commenting asking for status updates does not bump issue priority in any way and just serves to spam everyone subscribed to the issue.

@bradzacher bradzacher changed the title Rule enhancement for consistent-type-imports [consistent-type-imports] add option to autofix to a single type import May 3, 2022
@bradzacher
Copy link
Member

The fixStyle: "inline-type-imports" option was added in #5050 (v5.43.0).
https://typescript-eslint.io/rules/consistent-type-imports/#fixstyle
This will allow the rule to fix the imports to inline type specifiers.

This won't deduplicate your import declarations, however.

If you want then, then you can then use a rule like import/no-duplicates with the prefer-inline: true to collapse the imports (v2.27.0 of eslint-plugin-import):
https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-duplicates.md#inline-type-imports

You can also use import/consistent-type-specifier-style to enforce the use of inline OR top-level imports in your codebase (v2.27.0 of eslint-plugin-import):
https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/consistent-type-specifier-style.md

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepting prs Go ahead, send a pull request that resolves this issue enhancement: plugin rule option New rule option for an existing eslint-plugin rule package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants