oxc-project/oxc · warning · OxcDiagnostic

Type imports from declaration files must use top-level `impo

Error message

Type imports from declaration files must use top-level `import type` syntax.

What it means

oxlint's port of `import/consistent-type-specifier-style`. Independently of the configured mode, type imports from TypeScript declaration files (detected via `is_ts_declaration` on the resolved file extension, e.g. `.d.ts`) must use the top-level `import type` form; inline type specifiers on declaration-file imports are always reported by `use_top_level_for_declaration_file_import_diagnostic`.

Source

Thrown at crates/oxc_linter/src/rules/import/consistent_type_specifier_style.rs:25

    builder::AstBuilder,
};
use oxc_codegen::{Context, Gen};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{FileExtension, GetSpan, SPAN, Span};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{
    AstNode,
    context::LintContext,
    fixer::RuleFixer,
    rule::{DefaultRuleConfig, Rule},
};

fn use_top_level_for_declaration_file_import_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(
        "Type imports from declaration files must use top-level `import type` syntax.",
    )
    .with_help("Replace inline type specifiers with a top-level import type statement.")
    .with_label(span)
}

fn consistent_type_specifier_style_diagnostic(span: Span, mode: &Mode) -> OxcDiagnostic {
    let (warn_msg, help_msg) = match mode {
        Mode::Inline => (
            "Prefer using inline type specifiers instead of a top-level type-only import.",
            "Replace top‐level import type with an inline type specifier.",
        ),
        Mode::TopLevel => (
            "Prefer using a top-level type-only import instead of inline type specifiers.",
            "Replace inline type specifiers with a top‐level import type statement.",
        ),
        Mode::TopLevelIfOnlyTypeImports => (
            "Prefer using a top-level type-only import instead of inline type specifiers when there are only type imports.",

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Rewrite as `import type { Foo } from './types.d.ts';` (the rule ships a fixer that regenerates the statement)
  2. Keep any value imports from the same file in a separate non-type import statement
  3. Run `oxlint --fix` to convert all declaration-file imports at once

Example fix

// before
import { type Foo, type Bar } from './types.d.ts';

// after
import type { Foo, Bar } from './types.d.ts';
Defensive patterns

Strategy: validation

Validate before calling

// .oxlintrc.json
{
  "plugins": ["import"],
  "rules": { "import/consistent-type-specifier-style": "warn" }
}
// CI gate: npx oxlint src/

Prevention

When it happens

Trigger: `import { type Foo } from './types.d.ts';` under any mode — prefer-top-level (default), prefer-inline, or prefer-top-level-if-only-type-imports. The declaration-file check runs regardless of the mode option.

Common situations: Projects importing hand-written `.d.ts` ambient modules; type-only imports from `.d.mts`/`.d.cts` files; switching a repo to prefer-inline and discovering the declaration-file exception.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/2f1a7ebdd2422c9e. Report an issue: GitHub.