{"record":{"id":"a2a3a7c11ee9d3a3","repo":"oxc-project/oxc","slug":"unexpected-class-with-only-a-constructor","errorCode":null,"errorMessage":"Unexpected class with only a constructor.","messagePattern":"Unexpected class with only a constructor\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/typescript/no_extraneous_class.rs","lineNumber":112,"sourceCode":");\n\nfn empty_class_diagnostic(span: Span, has_decorators: bool) -> OxcDiagnostic {\n    let help = if has_decorators {\n        r#\"Set \"allowWithDecorator\": true in your config to allow empty decorated classes\"#\n    } else {\n        \"Delete this class\"\n    };\n    OxcDiagnostic::warn(\"Unexpected empty class.\").with_label(span).with_help(help)\n}\n\nfn only_static_no_extraneous_class_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unexpected class with only static properties.\")\n        .with_label(span)\n        .with_help(\"Try using standalone functions instead of static methods\")\n}\n\nfn only_constructor_no_extraneous_class_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unexpected class with only a constructor.\")\n        .with_label(span)\n        .with_help(\"Try replacing this class with a standalone function or deleting it entirely\")\n}\n\nimpl Rule for NoExtraneousClass {\n    fn from_configuration(value: serde_json::Value) -> Result<Self, serde_json::error::Error> {\n        DefaultRuleConfig::<Self>::from_value(value).map(DefaultRuleConfig::into_inner)\n    }\n\n    fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {\n        let AstKind::Class(class) = node.kind() else {\n            return;\n        };\n        if class.heritage.is_some() || (self.allow_with_decorator && !class.decorators.is_empty()) {\n            return;\n        }\n        let span = class.id.as_ref().map_or(class.span, |id| id.span);\n        let body = &class.body.body;","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/typescript/no_extraneous_class.rs#L94-L130","documentation":"Third diagnostic of no-extraneous-class: a class containing only a constructor is behaviourally just a function, so the rule suggests replacing it with a standalone function or deleting it (help at no_extraneous_class.rs:114-117).","triggerScenarios":"`class Point { constructor(x, y) { this.x = x; this.y = y; } }` with no methods, fields, or other members - the run() logic reports classes whose only member is the constructor.","commonSituations":"DTO or value-holder classes before real fields were added, generated stubs, refactoring leftovers where methods were moved out.","solutions":["Convert it to a factory function returning the object","Add real methods or fields if the class is meant to grow","Delete the class entirely if nothing depends on it"],"exampleFix":"// before\nclass Point {\n  constructor(public x: number, public y: number) {}\n}\n\n// after\nfunction makePoint(x: number, y: number) {\n  return { x, y };\n}","handlingStrategy":"validation","validationCode":"npx oxlint --deny-warnings .","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer factory functions for pure data holders","When scaffolding a class, add its first real member in the same commit","Watch refactors that strip methods: a constructor-only class is the usual residue"],"tags":["typescript","lint","class","constructor","refactor"],"backgroundTag":"extraneous-class","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}