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

eslint-plugin-lintlord

v1.1.0

Published

A collection of useful ESLint rules for cleaner, more maintainable TypeScript code

Readme


Why

Many codebases drift in two predictable ways:

interface LogsData {
  events: Array<{ name: string; createdAt: string }>;
}

function handleUpdate(params: { id: string; dryRun: boolean }) {
  console.log('updating', params.id);
}

Both patterns are convenient in the moment, but they age badly:

  • Shapes become hard to reuse when the same object structure appears in multiple places.
  • Types get harder to scan because important contracts are buried inside properties, parameters, and return types.
  • Debug leftovers slip into commits because console.log is fast to add and easy to forget.
  • Logging intent gets muddled when debugging output and intentional runtime messages look the same.
  • Refactoring is less ergonomic because named interfaces are easier to jump to, rename, and discuss in code review.
  • Consistency drifts over time when some teams extract types, some keep them inline, and console usage varies by file.

eslint-plugin-lintlord exists to enforce a small set of practical rules with clear payoffs:

  • When an object shape matters, give it a name.
  • When a log statement matters, make it intentional.

It is a good fit for teams that want:

  • More readable TypeScript APIs
  • Reusable interface contracts instead of duplicated { ... } shapes
  • Fewer accidental console.log leftovers in committed code
  • Clearer separation between debugging output and real logging
  • Better IDE navigation and review discussions
  • Gradual adoption for type cleanup, or strict autofix-driven enforcement

What it does

The plugin ships focused rules that target common TypeScript and JavaScript code problems:

| Rule | Description | Fixable | Recommended | Strict | | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------- | ----------- | -------- | | no-inline-interface-object-types | Disallow inline object type literals and extract them to named interfaces | ✅ | ⚠️ warn | ❌ error | | prefer-logger | Disallow console.log (or all console calls) in favor of a dedicated logger | 💡 | ❌ error | ❌ error |

no-inline-interface-object-types checks inline object types inside:

  • Interface properties
  • Function parameters
  • Method parameters
  • Arrow function parameters
  • Return types

When enabled with autofix: true, it can extract those inline shapes into generated interface names for you.

prefer-logger targets two common logging policies:

  • mode: 'log-only' flags only console.log and suggests console.info
  • mode: 'all' bans all console.* calls for teams using a dedicated logger

Examples

Type extraction

// Before
interface LogsData {
  events: Array<{ name: string; createdAt: string }>;
}

function handleUpdate(params: { id: string; dryRun: boolean }) {
  return { ok: !params.dryRun };
}

// After
interface LogsDataEvent {
  name: string;
  createdAt: string;
}

interface LogsData {
  events: Array<LogsDataEvent>;
}

interface HandleUpdateParams {
  id: string;
  dryRun: boolean;
}

interface HandleUpdateReturn {
  ok: boolean;
}

function handleUpdate(params: HandleUpdateParams): HandleUpdateReturn {
  return { ok: !params.dryRun };
}

Logging hygiene

// Before
console.log('server started on port', port);

// After
console.info('server started on port', port);

Or, in stricter teams:

// Before
console.warn('deprecated endpoint');

// After
logger.warn('deprecated endpoint');

The core benefit of the plugin is consistency in places where codebases usually drift: shared types and logging habits.


Installation

npm install --save-dev eslint-plugin-lintlord

Install the usual TypeScript ESLint pieces as peer dependencies:

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

Usage

Option A: Flat config with the built-in preset

// eslint.config.mjs
import lintlord from 'eslint-plugin-lintlord';
import tsParser from '@typescript-eslint/parser';

export default [
  {
    files: ['**/*.ts', '**/*.tsx'],
    languageOptions: {
      parser: tsParser,
    },
  },
  lintlord.configs.recommended,
];

Option B: Flat config with explicit rule options

// eslint.config.mjs
import lintlord from 'eslint-plugin-lintlord';
import tsParser from '@typescript-eslint/parser';

export default [
  {
    files: ['**/*.ts', '**/*.tsx'],
    languageOptions: {
      parser: tsParser,
    },
    plugins: {
      lintlord,
    },
    rules: {
      'lintlord/no-inline-interface-object-types': [
        'warn',
        {
          minMembersToExtract: 2,
        },
      ],
      'lintlord/prefer-logger': ['error', { mode: 'log-only' }],
    },
  },
];

Option C: Strict autofix mode

// eslint.config.mjs
import lintlord from 'eslint-plugin-lintlord';
import tsParser from '@typescript-eslint/parser';

export default [
  {
    files: ['**/*.ts', '**/*.tsx'],
    languageOptions: {
      parser: tsParser,
    },
  },
  lintlord.configs.strict,
];

Option D: Legacy .eslintrc setup

{
  "parser": "@typescript-eslint/parser",
  "plugins": ["lintlord"],
  "rules": {
    "lintlord/no-inline-interface-object-types": "warn",
    "lintlord/prefer-logger": ["error", { "mode": "log-only" }]
  }
}

Configs

| Config | Description | | ------------- | ------------------------------------------------------------------- | | recommended | Enables no-inline-interface-object-types at warn and prefer-logger at error | | strict | Enables no-inline-interface-object-types at error with autofix: true, and prefer-logger at error with mode: 'all' |

recommended is a good default if you want gradual type cleanup while still treating stray console.log calls as committed-code mistakes.

strict is better when your team already agrees on both patterns and wants automatic type extraction plus full logger enforcement.


Rule overview

no-inline-interface-object-types

The rule reports inline object literals such as:

function check(input: { value: string }) {}

and pushes code toward named interfaces:

interface CheckInput {
  value: string;
}

function check(input: CheckInput) {}

Useful options:

  • autofix: automatically extract named interfaces during eslint --fix
  • minMembersToExtract: allow very small inline shapes but extract larger ones
  • checkInterfaceProperties, checkFunctionParams, checkMethodParams, checkArrowFunctionParams, checkReturnTypes: enable or disable specific contexts

More examples and complete option details:

prefer-logger

Flags console.log as a debugging leftover and pushes toward intentional logging:

// ❌ reported — debug leftover
console.log('user id:', userId);

// ✅ allowed — intentional output (log-only mode default)
console.info('server started on port 3000');

A suggestion replaces console.log with console.info. For teams using a dedicated logger (pino, winston), set mode: 'all' to ban every console.* call.

Useful options:

  • mode: 'log-only' (default): restrict only console.log, suggest console.info
  • mode: 'all': restrict all console.* methods — enforce a dedicated logger

More examples and complete option details:


Documentation

Full documentation is available at drsmile444.github.io/eslint-plugin-lintlord.

Useful entry points:


Contributing

Contributions are welcome. If you want to propose a new rule or change behavior, open an issue first so the scope and rule design can be discussed before implementation.


License

MIT © Dmytro Vakulenko 🇺🇦