npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tianjos/eslint-plugin-elegant

v0.3.2

Published

Opinionated ESLint rules for elegant, behavior-rich TypeScript: no flag arguments, no type assertions, no null returns, no public mutable state, and small focused classes.

Readme

@tianjos/eslint-plugin-elegant

npm version license CI

Opinionated ESLint rules for elegant, behavior-rich TypeScript. The plugin pushes code toward intention-revealing functions, honest types, and encapsulated domain models — the kind of constraints that pay off in NestJS services and DDD-style codebases.

Install

npm install --save-dev @tianjos/eslint-plugin-elegant
pnpm add -D @tianjos/eslint-plugin-elegant
yarn add -D @tianjos/eslint-plugin-elegant

Peer dependencies

This plugin does not bundle ESLint or the TypeScript toolchain. Install them alongside it:

| Peer | Required version | | ----------------------------- | ---------------- | | eslint | >=9 | | typescript | >=5 | | @typescript-eslint/parser | >=8 |

npm install --save-dev eslint typescript @typescript-eslint/parser

Usage

This plugin targets flat config (eslint.config.mjs). The fastest way to adopt it is to spread the recommended ruleset:

// eslint.config.mjs
import parser from '@typescript-eslint/parser';
import elegant from '@tianjos/eslint-plugin-elegant';

export default [
  {
    files: ['src/**/*.ts'],
    languageOptions: {
      parser,
      parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
    },
    plugins: { elegant },
    rules: {
      ...elegant.configs.recommended.rules,
    },
  },
];

A complete, copy-pasteable example (including test-file overrides) lives in eslint.config.example.mjs.

Rules

The recommended config enables every custom rule plus the native max-params rule.

| Rule | Source | What it catches | recommended | | -------------------------------------- | ------ | ------------------------------------------------------------------------------- | ------------- | | elegant/no-boolean-param | custom | Boolean parameters (flag arguments) on functions, methods, and constructors | error | | elegant/max-class-methods | custom | Classes with more methods than the configured max (constructors excluded) | warn (max 10) | | elegant/no-type-assertion | custom | value as T and <T>value assertions (as const is allowed) | error | | elegant/no-null-return | custom | return null statements | error | | elegant/no-public-mutable-props | custom | Public, non-readonly class properties and public constructor parameter props | error | | elegant/no-logic-in-constructor | custom | Any constructor code beyond this.field = value stores and a super(...) call | error | | elegant/no-getters-setters | custom | get/set accessors (and getX/setX methods with { methods: true }) | error | | elegant/no-instanceof | custom | Use of the instanceof operator | error | | elegant/no-static-members | custom | Static methods, properties, accessors, and blocks (allowReadonly to permit constants) | error | | elegant/no-null | custom | The null literal as a value (type annotations and direct return null excepted) | error | | max-params | native | Functions declaring more than max parameters | warn (max 3) |

Rule details

no-boolean-param

A boolean argument almost always means the callee does two things. Prefer two intention-revealing functions or an options object. Flags both annotated (flag: boolean) and boolean-defaulted (flag = false) parameters.

max-class-methods

A proxy for the Single Responsibility Principle. Constructors are not counted; getters and setters are. Configurable via { max: number } (default 10).

no-type-assertion

Assertions silence the type checker. Reach for a type guard, a generic, or a correctly typed value instead. as const is permitted because it narrows rather than widens.

no-null-return

Keeps absence out of return values; model it with an explicit domain type or throw.

no-public-mutable-props

Public state should be readonly so callers cannot break an aggregate's invariants. private/protected members and readonly members are allowed.

no-logic-in-constructor

A constructor should only wire arguments to fields. Validation, transformation, and I/O belong in a static factory or a method, keeping object construction predictable. Parameter properties (constructor(private readonly x: T)) and a leading super(...) are allowed; computed right-hand sides (this.x = x * 2, this.items = items.slice()) and any non-assignment statement are flagged.

no-getters-setters

Getters and setters turn objects into data bags; prefer methods that expose behavior. Native get/set accessors (and accessor fields) are always flagged. The opt-in { methods: true } option also flags conventional getX/setX methods — useful for strict Elegant Objects style, but noisy around repositories and framework hooks, so it stays off in recommended.

no-instanceof

instanceof is type discrimination that belongs inside a polymorphic method on the object. Pairs with no-type-assertion to keep type-based branching out of the codebase.

no-static-members

Static state and behavior cannot be injected, substituted, or mocked. Prefer instances (with dependency injection) and a module-level const for shared values. The { allowReadonly: true } option permits static readonly constants. Note this also flags static factory methods (static create()), which are common; relax per-file if your design relies on them.

no-null

Completes no-null-return by banning the null literal as a value everywhere (const x = null, x === null, fn(null)), pushing absence into explicit types or undefined. null in type positions (string | null) and a direct return null (owned by no-null-return) are left alone. This is strict and will flag idioms like JSON.stringify(x, null, 2) — relax it in the files where you interoperate with null-based APIs.

Configuration

Overriding thresholds

max-class-methods and the native max-params both take a max option:

rules: {
  ...elegant.configs.recommended.rules,
  'elegant/max-class-methods': ['warn', { max: 15 }],
  'max-params': ['warn', { max: 4 }],
}

Relaxing rules in test files

Tests routinely use flag arguments and larger fixtures. Add a second config block scoped to your spec globs:

{
  files: ['**/*.spec.ts', '**/*.test.ts', '**/*.e2e-spec.ts'],
  rules: {
    'elegant/no-boolean-param': 'off',
    'elegant/max-class-methods': 'off',
    'max-params': 'off',
  },
}

Compatibility

The package ships a single CommonJS build that is consumable as both require('@tianjos/eslint-plugin-elegant') and an ESM import elegant from '@tianjos/eslint-plugin-elegant'. The exported object exposes { meta, rules, configs }.

License

MIT © Thiago