oxc-project/oxc · warning · OxcDiagnostic

Do not use an empty interface declaration.

Error message

Do not use an empty interface declaration.

What it means

Diagnostic from oxlint's port of typescript-eslint's no-empty-object-type rule. An interface with no members (interface Foo {}) behaves like the {} type and accepts any non-nullish value, so the rule bans it to prevent silent loss of type safety; the help text at crates/oxc_linter/src/rules/typescript/no_empty_object_type.rs:19 states exactly this. It fires when the rule visits an empty TSInterfaceDeclaration that the config (allowInterfaces, allowWithName) does not exempt.

Solutions

  1. Add at least one real member to the interface
  2. Replace it with a type alias that models the intended shape
  3. If you truly mean 'exactly the empty object', use `type Foo = Record<string, never>`
  4. Configure allowInterfaces or allowWithName in oxlintrc when the empty interface is intentional
  5. Suppress once with `// oxlint-disable-next-line typescript/no-empty-object-type`

Example fix

// before
interface User {}

// after
interface User {
  id: string;
}
Defensive patterns

Strategy: validation

Validate before calling

# .github/workflows/lint.yml
- run: npx oxlint --deny-warnings .

# or configure the exemption up front in oxlintrc.json
{
  "rules": {
    "typescript/no-empty-object-type": ["error", { "allowWithName": "^(?:I|Props|Params)$" }]
  }
}

Prevention

When it happens

Trigger: Writing `interface Foo {}` with an empty body; writing `interface Foo extends Bar {}` that adds no new members; an ambient .d.ts stub whose members were all removed; an interface whose name does not match the allowWithName regex.

Common situations: Placeholder types left over from prototyping, Flow-to-TypeScript migrations where empty interfaces were idiomatic, declaration merging that leaves one empty declaration, enabling the typescript restriction preset in oxlint which turns this rule on.

Related errors


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

Appendix: source

Thrown at crates/oxc_linter/src/rules/typescript/no_empty_object_type.rs:27

use oxc_macros::declare_oxc_lint;
use oxc_semantic::NodeId;
use oxc_span::Span;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

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

fn no_empty_object_type_diagnostic<S: Into<Cow<'static, str>>>(
    span: Span,
    message: S,
) -> OxcDiagnostic {
    OxcDiagnostic::warn(message)
        .with_help("To avoid confusion around the {} type allowing any non-nullish value, this rule bans usage of the {} type.")
        .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct NoEmptyObjectType(Box<NoEmptyObjectTypeConfig>);

#[expect(clippy::struct_field_names)]
#[derive(Debug, Default, Clone, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct NoEmptyObjectTypeConfig {
    /// Whether to allow empty interfaces.
    allow_interfaces: AllowInterfaces,
    /// Whether to allow empty object type literals.
    allow_object_types: AllowObjectTypes,
    /// A stringified regular expression to allow interfaces and object type aliases with the configured name.
    ///
    /// This can be useful if your existing code style includes a pattern of declaring empty types with `{}` instead of `object`.

View on GitHub (pinned to e1e7af627c)