Specialized rules for array and object manipulation, promoting efficient and readable data structure operations.
Rules for proper array method usage and patterns.
/**
* Prevents problematic array callback references
*/
'unicorn/no-array-callback-reference': 'error' | 'warn' | 'off' | [
'error' | 'warn',
{
ignoredFunctions?: string[]; // Default: []
}
];
/**
* Prevents array method this argument usage
*/
'unicorn/no-array-method-this-argument': 'error' | 'warn' | 'off';
/**
* Prevents direct array reverse mutations
*/
'unicorn/no-array-reverse': 'error' | 'warn' | 'off';
/**
* Requires explicit Array.join() separator
*/
'unicorn/require-array-join-separator': 'error' | 'warn' | 'off';Usage Examples:
// ❌ Bad - callback reference issues
const numbers = ['1', '2', '3'].map(Number);
// ✅ Good - explicit callback
const numbers = ['1', '2', '3'].map(string => Number(string));
// ❌ Bad - array method this argument
['a', 'b', 'c'].forEach(function(item) {
console.log(this.prefix + item);
}, { prefix: '>> ' });
// ✅ Good - arrow function or proper binding
const context = { prefix: '>> ' };
['a', 'b', 'c'].forEach(item => {
console.log(context.prefix + item);
});
// ❌ Bad - mutating reverse
const reversed = originalArray.reverse();
// ✅ Good - non-mutating reverse
const reversed = [...originalArray].reverse();
// ❌ Bad - implicit join separator
const csvLine = columns.join();
// ✅ Good - explicit join separator
const csvLine = columns.join(',');Rules for efficient array searching and element access.
/**
* 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 loop for finding indices
*/
'unicorn/prefer-array-index-of': 'error' | 'warn' | 'off';
/**
* Prefers Array.at() for element access with negative indices
*/
'unicorn/prefer-at': 'error' | 'warn' | 'off' | [
'error' | 'warn',
{
getLastElementFunctions?: string[]; // Default: ['pop', 'shift']
checkAllIndexAccess?: boolean; // Default: false
}
];Usage Examples:
// ❌ Bad - filter()[0] pattern
const user = users.filter(u => u.id === targetId)[0];
// ✅ Good - using find()
const user = users.find(u => u.id === targetId);
// ❌ Bad - using find() just to check existence
if (users.find(u => u.active)) {
// handle active users
}
// ✅ Good - using some() for existence check
if (users.some(u => u.active)) {
// handle active users
}
// ❌ Bad - manual loop for index finding
let index = -1;
for (let i = 0; i < items.length; i++) {
if (items[i] === target) {
index = i;
break;
}
}
// ✅ Good - using indexOf()
const index = items.indexOf(target);
// ❌ 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);Rules for modern array flattening and transformation methods.
/**
* Prefers Array.flat() over manual 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';
/**
* Prevents magic numbers in Array.flat() depth
*/
'unicorn/no-magic-array-flat-depth': 'error' | 'warn' | 'off';
/**
* Prevents unnecessary Array.flat() depth argument
*/
'unicorn/no-unnecessary-array-flat-depth': 'error' | 'warn' | 'off';
/**
* Prevents unnecessary Array.splice() count argument
*/
'unicorn/no-unnecessary-array-splice-count': '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(item => item.children).flat();
// ✅ Good - using flatMap()
const result = items.flatMap(item => item.children);
// ❌ Bad - magic number in flat depth
const deepFlattened = nested.flat(3);
// ✅ Good - named constant for depth
const NESTING_DEPTH = 3;
const deepFlattened = nested.flat(NESTING_DEPTH);
// ❌ Bad - unnecessary flat depth
const flattened = array.flat(1); // 1 is default
// ✅ Good - omit default depth
const flattened = array.flat();
// ❌ Bad - unnecessary splice count
array.splice(index); // Removes all elements from index
// ✅ Good - explicit when removing specific count
array.splice(index, 1); // Remove one elementRules for efficient object operations and transformations.
/**
* Prefers Object.fromEntries() over manual object construction
*/
'unicorn/prefer-object-from-entries': 'error' | 'warn' | 'off' | [
'error' | 'warn',
{
functions?: string[]; // Default: ['fromPairs']
}
];
/**
* Prevents unused object properties
*/
'unicorn/no-unused-properties': 'error' | 'warn' | 'off';Usage Examples:
// ❌ Bad - manual object construction from entries
const obj = {};
for (const [key, value] of entries) {
obj[key] = value;
}
// ✅ Good - using Object.fromEntries()
const obj = Object.fromEntries(entries);
// ❌ Bad - unused object properties
const config = {
apiUrl: 'https://api.example.com',
timeout: 5000,
retries: 3, // This property is never used
};
// ✅ Good - only used properties
const config = {
apiUrl: 'https://api.example.com',
timeout: 5000,
};Rules for efficient Set and Map operations.
/**
* Prefers Set.has() over array includes for large datasets
*/
'unicorn/prefer-set-has': 'error' | 'warn' | 'off';
/**
* Prefers Set.size over Set conversion to array for length
*/
'unicorn/prefer-set-size': 'error' | 'warn' | 'off';Usage Examples:
// ❌ Bad - array includes for large datasets
const allowedIds = [1, 2, 3, 4, 5, /* ... hundreds more */];
if (allowedIds.includes(userId)) {
// handle allowed user
}
// ✅ Good - Set.has() for better performance
const allowedIds = new Set([1, 2, 3, 4, 5, /* ... hundreds more */]);
if (allowedIds.has(userId)) {
// handle allowed user
}
// ❌ Bad - converting Set to array for length
const uniqueItems = new Set(items);
const count = [...uniqueItems].length;
// ✅ Good - using Set.size
const uniqueItems = new Set(items);
const count = uniqueItems.size;Rules for proper spread operator and destructuring usage.
/**
* Prefers spread syntax over legacy methods
*/
'unicorn/prefer-spread': 'error' | 'warn' | 'off';
/**
* Prevents useless spread operations
*/
'unicorn/no-useless-spread': 'error' | 'warn' | 'off';
/**
* Prevents useless fallback in spread operations
*/
'unicorn/no-useless-fallback-in-spread': 'error' | 'warn' | 'off';
/**
* Prevents unreadable array destructuring
*/
'unicorn/no-unreadable-array-destructuring': 'error' | 'warn' | 'off';
/**
* Enforces consistent destructuring patterns
*/
'unicorn/consistent-destructuring': 'error' | 'warn' | 'off';Usage Examples:
// ❌ Bad - using apply instead of spread
Math.max.apply(Math, numbers);
// ✅ Good - using spread syntax
Math.max(...numbers);
// ❌ Bad - useless spread
const result = [...[1, 2, 3]];
// ✅ Good - direct assignment
const result = [1, 2, 3];
// ❌ Bad - useless fallback in spread
const merged = [...(array || [])];
// ✅ Good - direct spread with proper fallback
const merged = array ? [...array] : [];
// ❌ Bad - unreadable array destructuring
const [, , , , , , , seventhItem] = array;
// ✅ Good - readable alternative
const seventhItem = array[6];
// ❌ Bad - inconsistent property access
function processUser(user) {
console.log(user.name);
console.log(user.email);
console.log(user.role);
}
// ✅ Good - consistent destructuring
function processUser(user) {
const { name, email, role } = user;
console.log(name);
console.log(email);
console.log(role);
}Rules for proper length checking and array index handling.
/**
* Prevents useless length checks
*/
'unicorn/no-useless-length-check': 'error' | 'warn' | 'off';
/**
* Prefers negative index access patterns
*/
'unicorn/prefer-negative-index': 'error' | 'warn' | 'off';
/**
* Prevents unnecessary slice end parameter
*/
'unicorn/no-unnecessary-slice-end': 'error' | 'warn' | 'off';Usage Examples:
// ❌ Bad - useless length check
if (array.length >= 1) {
// handle non-empty array
}
// ✅ Good - proper length check
if (array.length > 0) {
// handle non-empty array
}
// ❌ Bad - complex negative indexing
const lastTwo = array.slice(array.length - 2, array.length);
// ✅ Good - simple negative indexing
const lastTwo = array.slice(-2);
// ❌ Bad - unnecessary slice end
const copy = array.slice(0, array.length);
// ✅ Good - omit unnecessary end parameter
const copy = array.slice();export default [
{
plugins: {
unicorn: eslintPluginUnicorn,
},
rules: {
// Array method rules
'unicorn/no-array-callback-reference': 'error',
'unicorn/no-array-method-this-argument': 'error',
'unicorn/require-array-join-separator': 'error',
// Array search and access
'unicorn/prefer-array-find': 'error',
'unicorn/prefer-array-some': 'error',
'unicorn/prefer-array-index-of': 'error',
'unicorn/prefer-at': 'error',
// Array transformation
'unicorn/prefer-array-flat': 'error',
'unicorn/prefer-array-flat-map': 'error',
'unicorn/no-magic-array-flat-depth': 'error',
// Object operations
'unicorn/prefer-object-from-entries': 'error',
'unicorn/no-unused-properties': 'error',
// Set and Map operations
'unicorn/prefer-set-has': 'error',
'unicorn/prefer-set-size': 'error',
// Spread and destructuring
'unicorn/prefer-spread': 'error',
'unicorn/no-useless-spread': 'error',
'unicorn/consistent-destructuring': 'error',
},
},
];export default [
{
plugins: {
unicorn: eslintPluginUnicorn,
},
rules: {
// Optimize array operations
'unicorn/prefer-array-find': ['error', { checkFromLast: true }],
'unicorn/prefer-set-has': 'error', // Better for large datasets
'unicorn/prefer-at': ['error', { checkAllIndexAccess: true }],
// Prevent inefficient patterns
'unicorn/no-array-callback-reference': 'error',
'unicorn/no-useless-length-check': 'error',
'unicorn/prefer-spread': 'error',
// Modern array methods
'unicorn/prefer-array-flat-map': 'error',
'unicorn/prefer-array-flat': 'error',
},
},
];