or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

anti-pattern-prevention-rules.mdarray-object-rules.mdcode-quality-rules.mdcode-style-rules.mddom-browser-rules.mdimport-export-rules.mdindex.mdmodern-javascript-rules.mdplugin-configuration.md
tile.json

modern-javascript-rules.mddocs/

Modern JavaScript Rules

Rules that promote the use of modern JavaScript features, APIs, and patterns over legacy alternatives.

Capabilities

Prefer Array Methods

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

Prefer At Method

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

Prefer Modern String Methods

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

Prefer Modern Date and Math APIs

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

Prefer Modern DOM APIs

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

Prefer Code Point and Global APIs

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
}

Prefer Modern Event Handling

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

Prefer Modern Module Features

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

Prefer Top-Level Await

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

Configuration Examples

Comprehensive Modern JavaScript Setup

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