extraneousClasses
Reports classes used as static namespaces.
✅ This rule is included in the ts logicalStrict presets.
Classes that contain only static members or only a constructor can be replaced with simpler constructs. Static-only classes are often used as namespaces, but in JavaScript and TypeScript, individual module exports serve this purpose better. Classes with only a constructor can typically be replaced with standalone functions.
Using classes as static namespaces has several drawbacks:
- Wrapper classes add cognitive complexity without structural improvements
- Contents are already organized by being in a module
- IDEs provide better suggestions for module exports than static class properties
- Static analysis tools can more easily detect unused exports in modules
Examples
Section titled “Examples”class Empty {}class OnlyConstructor { constructor() { console.log("init"); }}class StaticUtils { static format(value: string) { return value.trim(); }
static parse(value: string) { return JSON.parse(value); }}class Constants { static readonly VERSION = "1.0.0"; static readonly MAX_SIZE = 100;}class Example { value = 42;}class Example { constructor(public value: number) {}}export function format(value: string) { return value.trim();}
export function parse(value: string) { return JSON.parse(value);}export const VERSION = "1.0.0";export const MAX_SIZE = 100;class Derived extends Base { static helper() { return 42; }}abstract class Base { abstract getValue(): number;}Options
Section titled “Options”allowEmpty
Section titled “allowEmpty”When set to true, allows empty classes with no members.
// Valid with { allowEmpty: true }class Empty {}allowConstructorOnly
Section titled “allowConstructorOnly”When set to true, allows classes that contain only a constructor.
// Valid with { allowConstructorOnly: true }class Example { constructor() { console.log("init"); }}allowStaticOnly
Section titled “allowStaticOnly”When set to true, allows classes that only contain static members.
// Valid with { allowStaticOnly: true }class Utils { static format(value: string) { return value.trim(); }}allowWithDecorator
Section titled “allowWithDecorator”When set to true, allows any extraneous class that includes a decorator.
This is useful for frameworks that use decorators to configure classes.
// Valid with { allowWithDecorator: true }@Injectable()class Service {}When Not To Use It
Section titled “When Not To Use It”If your codebase uses frameworks that rely heavily on class decorators for configuration (such as Angular or NestJS), you may want to enable allowWithDecorator for consistency.
Some legacy codebases may use classes as namespaces extensively, in which case migrating may not be practical.