@typescript-eslint/eslint-plugin
Version:
TypeScript plugin for ESLint
140 lines (98 loc) • 6.3 kB
text/mdx
---
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`
{/* insert option description */}
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`
{/* insert option description */}
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`
{/* insert option description */}
Examples of **incorrect** code with `{disallowTypeAnnotations: true}`:
```ts option='{ "disallowTypeAnnotations": true }' showPlaygroundButton
type T = import('Foo').Foo;
const x: import('Bar') = 1;
```
## Caveat: ` ` + `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](/getting-started/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`](/packages/parser/#emitdecoratormetadata) and [`parserOptions.experimentalDecorators = true`](/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 [`-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)