137 lines
6.4 KiB
Plaintext
137 lines
6.4 KiB
Plaintext
---
|
|
description: 'Enforce consistent usage of type imports.'
|
|
---
|
|
|
|
import Tabs from '@theme/Tabs';
|
|
import TabItem from '@theme/TabItem';
|
|
|
|
> 🛑 This file is source code, not the primary documentation location! 🛑
|
|
>
|
|
> See **https://typescript-eslint.io/rules/consistent-type-imports** for documentation.
|
|
|
|
TypeScript allows specifying a `type` keyword on imports to indicate that the export exists only in the type system, not at runtime.
|
|
This allows transpilers to drop imports without knowing the types of the dependencies.
|
|
|
|
> See [Blog > Consistent Type Exports and Imports: Why and How](/blog/consistent-type-imports-and-exports-why-and-how) for more details.
|
|
|
|
## Options
|
|
|
|
### `prefer`
|
|
|
|
This option defines the expected import kind for type-only imports. Valid values for `prefer` are:
|
|
|
|
- `type-imports` will enforce that you always use `import type Foo from '...'` except referenced by metadata of decorators. It is the default.
|
|
- `no-type-imports` will enforce that you always use `import Foo from '...'`.
|
|
|
|
Examples of **correct** code with `{prefer: 'type-imports'}`, and **incorrect** code with `{prefer: 'no-type-imports'}`.
|
|
|
|
```ts option='{ "prefer": "type-imports" }' showPlaygroundButton
|
|
import type { Foo } from 'Foo';
|
|
import type Bar from 'Bar';
|
|
type T = Foo;
|
|
const x: Bar = 1;
|
|
```
|
|
|
|
Examples of **incorrect** code with `{prefer: 'type-imports'}`, and **correct** code with `{prefer: 'no-type-imports'}`.
|
|
|
|
```ts option='{ "prefer": "type-imports" }' showPlaygroundButton
|
|
import { Foo } from 'Foo';
|
|
import Bar from 'Bar';
|
|
type T = Foo;
|
|
const x: Bar = 1;
|
|
```
|
|
|
|
### `fixStyle`
|
|
|
|
This option defines the expected type modifier to be added when an import is detected as used only in the type position. Valid values for `fixStyle` are:
|
|
|
|
- `separate-type-imports` will add the type keyword after the import keyword `import type { A } from '...'`. It is the default.
|
|
- `inline-type-imports` will inline the type keyword `import { type A } from '...'` and is only available in TypeScript 4.5 and onwards. See [documentation here](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#type-modifiers-on-import-names 'TypeScript 4.5 documentation on type modifiers and import names').
|
|
|
|
<Tabs>
|
|
<TabItem value="❌ Incorrect">
|
|
|
|
```ts
|
|
import { Foo } from 'Foo';
|
|
import Bar from 'Bar';
|
|
type T = Foo;
|
|
const x: Bar = 1;
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="✅ With `separate-type-imports`">
|
|
|
|
```ts option='{ "fixStyle": "separate-type-imports" }'
|
|
import type { Foo } from 'Foo';
|
|
import type Bar from 'Bar';
|
|
type T = Foo;
|
|
const x: Bar = 1;
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="✅ With `inline-type-imports`">
|
|
|
|
```ts option='{ "fixStyle": "inline-type-imports" }'
|
|
import { type Foo } from 'Foo';
|
|
import type Bar from 'Bar';
|
|
type T = Foo;
|
|
const x: Bar = 1;
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
### `disallowTypeAnnotations`
|
|
|
|
If `true`, type imports in type annotations (`import()`) are not allowed.
|
|
Default is `true`.
|
|
|
|
Examples of **incorrect** code with `{disallowTypeAnnotations: true}`:
|
|
|
|
```ts option='{ "disallowTypeAnnotations": true }' showPlaygroundButton
|
|
type T = import('Foo').Foo;
|
|
const x: import('Bar') = 1;
|
|
```
|
|
|
|
## Caveat: `@decorators` + `experimentalDecorators: true` + `emitDecoratorMetadata: true`
|
|
|
|
:::note
|
|
If you are using `experimentalDecorators: false` (eg [TypeScript v5.0's stable decorators](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#decorators)) then the rule will always report errors as expected.
|
|
This caveat **only** applies to `experimentalDecorators: true`
|
|
:::
|
|
|
|
The rule will **_not_** report any errors in files _that contain decorators_ when **both** `experimentalDecorators` and `emitDecoratorMetadata` are turned on.
|
|
|
|
> See [Blog > Changes to consistent-type-imports when used with legacy decorators and decorator metadata](/blog/changes-to-consistent-type-imports-with-decorators) for more details.
|
|
|
|
If you are using [type-aware linting](https://typescript-eslint.io/linting/typed-linting) then we will automatically infer your setup from your tsconfig and you should not need to configure anything.
|
|
Otherwise you can explicitly tell our tooling to analyze your code as if the compiler option was turned on by setting both [`parserOptions.emitDecoratorMetadata = true`](https://typescript-eslint.io/packages/parser/#emitdecoratormetadata) and [`parserOptions.experimentalDecorators = true`](https://typescript-eslint.io/packages/parser/#experimentaldecorators).
|
|
|
|
## Comparison with `importsNotUsedAsValues` / `verbatimModuleSyntax`
|
|
|
|
[`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax) was introduced in TypeScript v5.0 (as a replacement for `importsNotUsedAsValues`).
|
|
This rule and `verbatimModuleSyntax` _mostly_ behave in the same way.
|
|
There are a few behavior differences:
|
|
| Situation | `consistent-type-imports` (ESLint) | `verbatimModuleSyntax` (TypeScript) |
|
|
| -------------------------------------------------------------- | --------------------------------------------------------- | ----------------------------------------------------------- |
|
|
| Unused imports | Ignored (consider using [`@typescript-eslint/no-unused-vars`](/rules/no-unused-vars)) | Type error |
|
|
| Usage with `emitDecoratorMetadata` & `experimentalDecorations` | Ignores files that contain decorators | Reports on files that contain decorators |
|
|
| Failures detected | Does not fail `tsc` build; can be auto-fixed with `--fix` | Fails `tsc` build; cannot be auto-fixed on the command-line |
|
|
| `import { type T } from 'T';` | TypeScript will emit nothing (it "elides" the import) | TypeScript emits `import {} from 'T'` |
|
|
|
|
Because there are some differences, using both this rule and `verbatimModuleSyntax` at the same time can lead to conflicting errors.
|
|
As such we recommend that you only ever use one _or_ the other -- never both.
|
|
|
|
## When Not To Use It
|
|
|
|
If you specifically want to use both import kinds for stylistic reasons, or don't wish to enforce one style over the other, you can avoid this rule.
|
|
|
|
However, keep in mind that inconsistent style can harm readability in a project.
|
|
We recommend picking a single option for this rule that works best for your project.
|
|
|
|
## Related To
|
|
|
|
- [`no-import-type-side-effects`](./no-import-type-side-effects.mdx)
|
|
- [`import/consistent-type-specifier-style`](https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/consistent-type-specifier-style.md)
|
|
- [`import/no-duplicates` with `{"prefer-inline": true}`](https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-duplicates.md#inline-type-imports)
|