oxc-project/oxc · warning · OxcDiagnostic
Unexpected class with only static properties.
Error message
Unexpected class with only static properties.
What it means
Second diagnostic of no-extraneous-class: a class whose every member is static is a namespace in disguise, so the rule flags it. The help at no_extraneous_class.rs:108-111 recommends standalone functions instead of static methods.
Source
Thrown at crates/oxc_linter/src/rules/typescript/no_extraneous_class.rs:106
typescript,
suspicious,
dangerous_suggestion,
config = NoExtraneousClass,
version = "0.7.0",
short_description = "Disallow classes used as namespaces.",
);
fn empty_class_diagnostic(span: Span, has_decorators: bool) -> OxcDiagnostic {
let help = if has_decorators {
r#"Set "allowWithDecorator": true in your config to allow empty decorated classes"#
} else {
"Delete this class"
};
OxcDiagnostic::warn("Unexpected empty class.").with_label(span).with_help(help)
}
fn only_static_no_extraneous_class_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Unexpected class with only static properties.")
.with_label(span)
.with_help("Try using standalone functions instead of static methods")
}
fn only_constructor_no_extraneous_class_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Unexpected class with only a constructor.")
.with_label(span)
.with_help("Try replacing this class with a standalone function or deleting it entirely")
}
impl Rule for NoExtraneousClass {
fn from_configuration(value: serde_json::Value) -> Result<Self, serde_json::error::Error> {
DefaultRuleConfig::<Self>::from_value(value).map(DefaultRuleConfig::into_inner)
}
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let AstKind::Class(class) = node.kind() else {
return;View on GitHub (pinned to e1e7af627c)
Solutions
- Export plain functions from the module instead
- Replace the class with a frozen object literal or a TS namespace
- Add an instance member if the class genuinely models state
- Disable inline when the grouping is deliberate
Example fix
// before
class Str {
static trim(s: string) { return s.trim(); }
}
const t = Str.trim(x);
// after
export function trim(s: string) { return s.trim(); }
const t = trim(x); Defensive patterns
Strategy: validation
Validate before calling
npx oxlint --deny-warnings .
Prevention
- Default to exported functions for utility code; reach for a class only when there is instance state
- Codemod static utility classes to module functions early in a migration
- Flag all-static classes in code review as a namespace smell
When it happens
Trigger: `class MathUtils { static add(...) {} static sub(...) {} }` - every class element is a static member with no instance state.
Common situations: Utility bags written out of Java or C# habit, helpers grouped into a class purely for namespacing or editor discoverability.
Related errors
- Unexpected class with only a constructor.
- Literals should be exposed using readonly fields.
- Literals should be exposed using getters.
- Missing accessibility modifier on {member_type} {name}.
- Public accessibility modifier on {member_type} {name}.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/b8bd95bcfbb2ca7d.
Report an issue: GitHub.