{"record":{"id":"a43c468c085dff9d","repo":"oxc-project/oxc","slug":"unexpected-empty-class","errorCode":null,"errorMessage":"Unexpected empty class.","messagePattern":"Unexpected empty class\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/typescript/no_extraneous_class.rs","lineNumber":102,"sourceCode":"    /// const version = 42;\n    /// const isProduction = () => process.env.NODE_ENV === 'production';\n    /// ```\n    NoExtraneousClass,\n    typescript,\n    suspicious,\n    dangerous_suggestion,\n    config = NoExtraneousClass,\n    version = \"0.7.0\",\n    short_description = \"Disallow classes used as namespaces.\",\n);\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    }","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/typescript/no_extraneous_class.rs#L84-L120","documentation":"First diagnostic of oxlint's no-extraneous-class: a class declaration with no body members is flagged as 'Unexpected empty class.' because such classes typically act as namespace or marker placeholders. When the class carries decorators, the help at no_extraneous_class.rs:104-108 instead points to the allowWithDecorator config option.","triggerScenarios":"`class Foo {}` with an empty body; an empty class annotated with decorators (for example an Angular or NestJS anchor class) while allowWithDecorator is false (the default).","commonSituations":"Decorator-based frameworks that need empty classes as anchors, scaffolding leftovers, classes kept 'for later' that never gained members.","solutions":["Delete the class if nothing uses it","Add the members it is meant to hold","For decorator-anchored empty classes, set allowWithDecorator: true in the rule config","Suppress inline with an oxlint-disable comment when intentional"],"exampleFix":"// before\nclass ApiError {}\n\n// after\nclass ApiError extends Error {\n  constructor(message: string) {\n    super(message);\n  }\n}","handlingStrategy":"validation","validationCode":"npx oxlint --deny-warnings .\n\n# decorator-heavy codebase:\n{\n  \"rules\": { \"typescript/no-extraneous-class\": [\"error\", { \"allowWithDecorator\": true }] }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Delete scaffolded empty classes in the same commit that removes their last use","For Angular/NestJS codebases, set allowWithDecorator up front instead of fighting the rule per line","Treat 'class with no members' as dead code in review"],"tags":["typescript","lint","class","dead-code"],"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"}