ESLint Plugin Utils
raw JSON → 0.4.1 verified Sat Apr 25 auth: no javascript
eslint-plugin-utils is a utility library for building ESLint plugins and custom rules, developed as part of the un-ts monorepo. The current stable version is 0.4.1, released in December 2024, with a focus on compatibility with ESLint flat config and TypeScript. It provides helpers for rule creation, schema validation, and AST traversal, reducing boilerplate for ESLint plugin authors. Key differentiators include first-class TypeScript support with bundled types, dependency on @typescript-eslint/utils for type-safe rule creation, and support for both legacy and flat ESLint configurations. The package follows semver and is updated as part of a monorepo with several related plugins (text, markup, htm).
Common errors
error Cannot find module 'eslint-plugin-utils' or its corresponding type declarations. ↓
cause Package is ESM-only and not resolved properly in TypeScript without 'moduleResolution': 'node16' or 'bundler'.
fix
Set 'moduleResolution' to 'node16' or 'bundler' in tsconfig.json, or use 'esModuleInterop'.
error TypeError: createRule is not a function ↓
cause Attempted to use require() to import the package, but it's ESM-only.
fix
Change to import statement: import { createRule } from 'eslint-plugin-utils'
error Error: Cannot use 'in' operator to search for 'create' in undefined ↓
cause Missing defaultOptions in rule definition when using createRule with no defaultOptions provided.
fix
Add defaultOptions: [] to the rule definition.
error Error: The 'parserServices' property requires TypeScript and @typescript-eslint/parser to be used. ↓
cause Using TypeScript-specific utilities without the required parser and plugin.
fix
Ensure you have @typescript-eslint/parser installed and configured in ESLint config.
Warnings
breaking ESM-only since 0.4.0; require() is no longer supported. ↓
fix Use import syntax instead of require(). If using CommonJS, upgrade to ESM or stick with v0.3.x.
breaking Default export removed in 0.4.0; use named exports. ↓
fix Replace import eslintPluginUtils from 'eslint-plugin-utils' with import * as utils from 'eslint-plugin-utils' or destructure named exports.
deprecated The createRule function no longer accepts a 'create' callback without defaultOptions - use defaultOptions array in create. ↓
fix Ensure you pass defaultOptions as part of the rule definition, even if empty array.
gotcha The getFilename function may return undefined in flat config if used without a file name. ↓
fix Always provide a filename in flat config context or handle undefined case.
gotcha RuleTester from eslint-plugin-utils requires @typescript-eslint/utils as peer dependency; may cause missing package errors if not installed. ↓
fix Install @typescript-eslint/utils as a dev dependency: npm install --save-dev @typescript-eslint/utils
deprecated The 'recommended' meta property is deprecated in favor of 'recommended' being a string severity in 'docs.recommended'? Verify with ESLint docs. ↓
fix Use 'docs.recommended' as string like 'error' or 'warn' instead of boolean.
Install
npm install eslint-plugin-utils yarn add eslint-plugin-utils pnpm add eslint-plugin-utils Imports
- createRule wrong
const { createRule } = require('eslint-plugin-utils')correctimport { createRule } from 'eslint-plugin-utils' - default wrong
import * as utils from 'eslint-plugin-utils'correctimport eslintPluginUtils from 'eslint-plugin-utils' - getFilename
import { getFilename } from 'eslint-plugin-utils' - RuleTester
import { RuleTester } from 'eslint-plugin-utils'
Quickstart
import { createRule } from 'eslint-plugin-utils';
export const myRule = createRule({
name: 'my-rule',
meta: {
type: 'suggestion',
docs: {
description: 'Description of my rule',
recommended: 'error',
},
fixable: 'code',
schema: [
{ type: 'string' }
],
},
defaultOptions: ['defaultOption'],
create: (context, optionsWithDefault) => {
return {
Literal: (node) => {
const [option] = optionsWithDefault;
if (typeof node.value !== 'string') return;
if (node.value === option) {
context.report({
node,
message: 'Avoid using the default option: {{ option }}',
data: { option },
fix: (fixer) => fixer.replaceText(node, `'changed'`),
});
}
},
};
},
});