Skip to main content
interlace
Plugin: import-nextRules

consistent-type-specifier-style

Enforce or ban the use of inline type-only markers for named imports

💼 This rule is enabled in the following configs: recommended, typescript. 🔧 This rule is automatically fixable by the --fix CLI option.

Rule Details

TypeScript lets a type-only import be written two ways: a top-level import type { A } from 'm', or an inline qualifier on the specifier, import { type A } from 'm'. This rule enforces the one your project chose.

  • prefer-inline (default) reports a top-level import type { ... } that has named specifiers; the fix moves type onto each specifier. A type-only default or namespace import (import type D from 'm', import type * as N from 'm') has no inline form and is not reported.
  • prefer-top-level reports every inline type qualifier, also one next to value specifiers or a default binding (import { type A, b } from 'm'): the type names belong in their own import type statement. The fix rewrites a block whose specifiers are all types; a mixed block is reported without a fix, since rewriting it in place would turn its values into types.

Export statements are not checked.

❌ Incorrect

// prefer-inline (default)
import type { User, Role } from './models';

// prefer-top-level
import { type User, type Role } from './models';
import { type User, loadUser } from './models';

✅ Correct

// prefer-inline (default)
import { type User, type Role } from './models';
import type Config from './config';

// prefer-top-level
import type { User, Role } from './models';
import { loadUser } from './models';

Options

[
  {
    "type": "string",
    "enum": [
      "prefer-inline",
      "prefer-top-level"
    ],
    "default": "prefer-inline"
  }
]

A single string, prefer-inline (default) or prefer-top-level.

When Not To Use It

When your codebase mixes both styles on purpose, for example because verbatimModuleSyntax makes import { type A } keep a side-effect import of the module while import type erases it, and you rely on that difference.

Use this rule

npm install -D oxlint-plugin-import-next
.oxlintrc.json
{  "jsPlugins": ["oxlint-plugin-import-next"],  "rules": {    "import-next/consistent-type-specifier-style": "error"  }}
vite.config.ts
import { defineConfig } from 'vite-plus';export default defineConfig({  lint: {    jsPlugins: ['oxlint-plugin-import-next'],    rules: {      'import-next/consistent-type-specifier-style': 'error',    },  },});

oxlint-plugin-import-next re-exports eslint-plugin-import-next/oxlint: the same rules under the same IDs, and no ESLint install. Why oxlint.

Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.