CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-eslint-plugin-unicorn

More than 100 powerful ESLint rules for enforcing code quality, consistency, and modern JavaScript best practices

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

array-object-rules.mddocs/

Array and Object Rules

Specialized rules for array and object manipulation, promoting efficient and readable data structure operations.

Capabilities

Array Method Rules

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(',');

Array Search and Access Rules

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);

Array Flattening and Transformation Rules

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 element

Object Method Rules

Rules 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,
};

Set and Map Rules

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;

Spread and Destructuring Rules

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);
}

Length and Index Rules

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();

Configuration Examples

Comprehensive Array and Object Rules

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',
    },
  },
];

Performance-Focused Configuration

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',
    },
  },
];

docs

anti-pattern-prevention-rules.md

array-object-rules.md

code-quality-rules.md

code-style-rules.md

dom-browser-rules.md

import-export-rules.md

index.md

modern-javascript-rules.md

plugin-configuration.md

tile.json