More than 100 powerful ESLint rules for enforcing code quality, consistency, and modern JavaScript best practices
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Rules that promote the use of modern JavaScript features, APIs, and patterns over legacy alternatives.
Modern array methods that provide better performance and readability.
/**
* Prefers Array.flat() over manual array flattening
*/
'unicorn/prefer-array-flat': 'error' | 'warn' | 'off' | [
'error' | 'warn',
{
functions?: string[]; // Default: ['concat', 'apply']
}
];
/**
* Prefers Array.flatMap() over map().flat() combination
*/
'unicorn/prefer-array-flat-map': 'error' | 'warn' | 'off';
/**
* Prefers Array.find() over filter()[0] patterns
*/
'unicorn/prefer-array-find': 'error' | 'warn' | 'off' | [
'error' | 'warn',
{
checkFromLast?: boolean; // Default: false
}
];
/**
* Prefers Array.some() over find() when checking existence
*/
'unicorn/prefer-array-some': 'error' | 'warn' | 'off';
/**
* Prefers Array.indexOf() over manual iteration for finding indices
*/
'unicorn/prefer-array-index-of': 'error' | 'warn' | 'off';Usage Examples:
// ❌ Bad - manual array flattening
const flattened = [].concat(...arrays);
// ✅ Good - using Array.flat()
const flattened = arrays.flat();
// ❌ Bad - map then flat
const result = items.map(transform).flat();
// ✅ Good - using flatMap
const result = items.flatMap(transform);
// ❌ Bad - filter()[0] pattern
const found = items.filter(item => item.id === id)[0];
// ✅ Good - using find()
const found = items.find(item => item.id === id);Prefers Array.at() and String.at() for accessing elements with negative indices.
/**
* Prefers .at() method for array and string element access
* Particularly useful with negative indices
*/
'unicorn/prefer-at': 'error' | 'warn' | 'off' | [
'error' | 'warn',
{
getLastElementFunctions?: string[]; // Default: ['pop', 'shift']
checkAllIndexAccess?: boolean; // Default: false
}
];Usage Examples:
// ❌ Bad - complex negative indexing
const lastItem = array[array.length - 1];
const secondToLast = array[array.length - 2];
// ✅ Good - using .at() method
const lastItem = array.at(-1);
const secondToLast = array.at(-2);
// ❌ Bad - string character access
const lastChar = string[string.length - 1];
// ✅ Good - using .at() for strings
const lastChar = string.at(-1);Modern string methods for better readability and performance.
/**
* Prefers String.includes() over indexOf() !== -1
*/
'unicorn/prefer-includes': 'error' | 'warn' | 'off';
/**
* Prefers String.startsWith() and String.endsWith()
*/
'unicorn/prefer-string-starts-ends-with': 'error' | 'warn' | 'off';
/**
* Prefers String.slice() over String.substr() and String.substring()
*/
'unicorn/prefer-string-slice': 'error' | 'warn' | 'off';
/**
* Prefers String.replaceAll() over String.replace() with global regex
*/
'unicorn/prefer-string-replace-all': 'error' | 'warn' | 'off';
/**
* Prefers String.trimStart() and String.trimEnd() over trimLeft()/trimRight()
*/
'unicorn/prefer-string-trim-start-end': 'error' | 'warn' | 'off';
/**
* Prefers String.raw for template literals with backslashes
*/
'unicorn/prefer-string-raw': 'error' | 'warn' | 'off';Usage Examples:
// ❌ Bad - indexOf() for existence check
if (string.indexOf('substring') !== -1) {
// handle found
}
// ✅ Good - using includes()
if (string.includes('substring')) {
// handle found
}
// ❌ Bad - manual prefix/suffix checking
if (string.indexOf('prefix') === 0) {
// handle prefix
}
// ✅ Good - using startsWith()
if (string.startsWith('prefix')) {
// handle prefix
}
// ❌ Bad - global replace with regex
const result = text.replace(/old/g, 'new');
// ✅ Good - using replaceAll()
const result = text.replaceAll('old', 'new');Modern Date and Math methods for better precision and readability.
/**
* Prefers Date.now() over new Date().getTime()
*/
'unicorn/prefer-date-now': 'error' | 'warn' | 'off';
/**
* Prefers Math.trunc() over bitwise operations for truncation
*/
'unicorn/prefer-math-trunc': 'error' | 'warn' | 'off' | [
'error' | 'warn',
{
checkDefaultCase?: boolean; // Default: false
}
];
/**
* Prefers Math.min() and Math.max() over ternary operators
*/
'unicorn/prefer-math-min-max': 'error' | 'warn' | 'off';
/**
* Prefers modern Math APIs over manual implementations
*/
'unicorn/prefer-modern-math-apis': 'error' | 'warn' | 'off';Usage Examples:
// ❌ Bad - verbose date timestamp
const timestamp = new Date().getTime();
// ✅ Good - using Date.now()
const timestamp = Date.now();
// ❌ Bad - bitwise truncation
const truncated = ~~number;
// ✅ Good - using Math.trunc()
const truncated = Math.trunc(number);
// ❌ Bad - ternary for min/max
const min = a < b ? a : b;
// ✅ Good - using Math.min()
const min = Math.min(a, b);Modern DOM methods that replace older patterns.
/**
* Prefers modern DOM APIs over legacy methods
*/
'unicorn/prefer-modern-dom-apis': 'error' | 'warn' | 'off';
/**
* Prefers Node.append() over Node.appendChild()
*/
'unicorn/prefer-dom-node-append': 'error' | 'warn' | 'off';
/**
* Prefers Node.remove() over parentNode.removeChild()
*/
'unicorn/prefer-dom-node-remove': 'error' | 'warn' | 'off';
/**
* Prefers Node.textContent over Node.innerText
*/
'unicorn/prefer-dom-node-text-content': 'error' | 'warn' | 'off';
/**
* Prefers dataset API over getAttribute/setAttribute for data attributes
*/
'unicorn/prefer-dom-node-dataset': 'error' | 'warn' | 'off';Usage Examples:
// ❌ Bad - legacy DOM methods
element.appendChild(child);
parent.removeChild(element);
element.setAttribute('data-value', 'test');
// ✅ Good - modern DOM APIs
element.append(child);
element.remove();
element.dataset.value = 'test';
// ❌ Bad - using innerText
element.innerText = 'Hello';
// ✅ Good - using textContent
element.textContent = 'Hello';Modern Unicode and global object access patterns.
/**
* Prefers String.codePointAt() over String.charCodeAt()
*/
'unicorn/prefer-code-point': 'error' | 'warn' | 'off';
/**
* Prefers globalThis over window, global, or self
*/
'unicorn/prefer-global-this': 'error' | 'warn' | 'off';
/**
* Prefers Number properties over global functions
*/
'unicorn/prefer-number-properties': 'error' | 'warn' | 'off' | [
'error' | 'warn',
{
checkInfinity?: boolean; // Default: true
checkNaN?: boolean; // Default: true
}
];Usage Examples:
// ❌ Bad - legacy Unicode handling
const code = string.charCodeAt(0);
// ✅ Good - modern Unicode handling
const code = string.codePointAt(0);
// ❌ Bad - environment-specific global access
const global = window || global || self;
// ✅ Good - using globalThis
const global = globalThis;
// ❌ Bad - global functions
if (isNaN(value)) {
// handle NaN
}
// ✅ Good - Number properties
if (Number.isNaN(value)) {
// handle NaN
}Modern event handling patterns over legacy approaches.
/**
* Prefers addEventListener over on* properties
*/
'unicorn/prefer-add-event-listener': 'error' | 'warn' | 'off' | [
'error' | 'warn',
{
excludedPackages?: string[]; // Default: ['koa', 'sax']
}
];
/**
* Prefers EventTarget over other event handling patterns
*/
'unicorn/prefer-event-target': 'error' | 'warn' | 'off';
/**
* Prefers KeyboardEvent.key over KeyboardEvent.keyCode
*/
'unicorn/prefer-keyboard-event-key': 'error' | 'warn' | 'off';Usage Examples:
// ❌ Bad - legacy event handling
element.onclick = handleClick;
// ✅ Good - modern event handling
element.addEventListener('click', handleClick);
// ❌ Bad - legacy keyboard event handling
document.addEventListener('keydown', (event) => {
if (event.keyCode === 13) {
// handle Enter key
}
});
// ✅ Good - modern keyboard event handling
document.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
// handle Enter key
}
});Modern ES module features and import.meta properties.
/**
* Prefers ES modules over CommonJS
*/
'unicorn/prefer-module': 'error' | 'warn' | 'off' | [
'error' | 'warn',
{
checkDefaultCase?: boolean; // Default: false
}
];
/**
* Prefers import.meta properties over alternatives
*/
'unicorn/prefer-import-meta-properties': 'error' | 'warn' | 'off';
/**
* Prefers node: protocol for Node.js built-in modules
*/
'unicorn/prefer-node-protocol': 'error' | 'warn' | 'off';
/**
* Prefers export-from syntax when re-exporting
*/
'unicorn/prefer-export-from': 'error' | 'warn' | 'off' | [
'error' | 'warn',
{
ignoreUsedVariables?: boolean; // Default: false
}
];Usage Examples:
// ❌ Bad - CommonJS require
const fs = require('fs');
// ✅ Good - ES module import with node: protocol
import fs from 'node:fs';
// ❌ Bad - __dirname in ES modules
const currentDir = __dirname;
// ✅ Good - import.meta.url
const currentDir = new URL('.', import.meta.url).pathname;
// ❌ Bad - manual re-export
import { helper } from './utils.js';
export { helper };
// ✅ Good - export-from syntax
export { helper } from './utils.js';Modern async patterns using top-level await.
/**
* Prefers top-level await over IIFE patterns
*/
'unicorn/prefer-top-level-await': 'error' | 'warn' | 'off';Usage Examples:
// ❌ Bad - IIFE for async in module scope
(async () => {
const data = await fetchData();
console.log(data);
})();
// ✅ Good - top-level await
const data = await fetchData();
console.log(data);export default [
{
plugins: {
unicorn: eslintPluginUnicorn,
},
rules: {
// Modern array methods
'unicorn/prefer-array-flat': 'error',
'unicorn/prefer-array-flat-map': 'error',
'unicorn/prefer-array-find': 'error',
'unicorn/prefer-array-some': 'error',
'unicorn/prefer-at': 'error',
// Modern string methods
'unicorn/prefer-includes': 'error',
'unicorn/prefer-string-starts-ends-with': 'error',
'unicorn/prefer-string-slice': 'error',
'unicorn/prefer-string-replace-all': 'error',
'unicorn/prefer-string-trim-start-end': 'error',
// Modern APIs
'unicorn/prefer-date-now': 'error',
'unicorn/prefer-math-trunc': 'error',
'unicorn/prefer-global-this': 'error',
'unicorn/prefer-number-properties': 'error',
// Modern modules
'unicorn/prefer-module': 'error',
'unicorn/prefer-node-protocol': 'error',
'unicorn/prefer-top-level-await': 'error',
},
},
];