CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-typescript-eslint--eslint-plugin

TypeScript plugin for ESLint providing comprehensive lint rules for TypeScript codebases

Pending
Overview
Eval results
Files

best-practices-rules.mddocs/

Best Practices Rules

Rules that promote TypeScript and JavaScript best practices, preventing common pitfalls and anti-patterns. These rules help developers write more maintainable, performant, and error-resistant code.

Capabilities

Modern Language Features

Rules that encourage the use of modern JavaScript and TypeScript features.

/**
 * Prefer optional chaining over chained logical ands
 */
"prefer-optional-chain": RuleModule;

/**
 * Enforce nullish coalescing over logical OR
 */
"prefer-nullish-coalescing": RuleModule;

/**
 * Prefer as const over literal type assertions
 */
"prefer-as-const": RuleModule;

/**
 * Prefer for-of loop over traditional for loop when possible
 */
"prefer-for-of": RuleModule;

/**
 * Prefer includes method over indexOf method
 */
"prefer-includes": RuleModule;

/**
 * Prefer string startsWith/endsWith over substring/indexOf
 */
"prefer-string-starts-ends-with": RuleModule;

/**
 * Prefer destructuring from arrays and objects
 */
"prefer-destructuring": RuleModule;

Usage Examples:

// ❌ Bad - prefer-optional-chain
if (user && user.profile && user.profile.settings) {
  // Access user.profile.settings
}

// ✅ Good
if (user?.profile?.settings) {
  // Access user.profile.settings
}

// ❌ Bad - prefer-nullish-coalescing
const name = user.name || 'Anonymous'; // Wrong for empty string

// ✅ Good
const name = user.name ?? 'Anonymous'; // Only null/undefined

// ❌ Bad - prefer-includes
if (items.indexOf(item) !== -1) {} // Verbose

// ✅ Good
if (items.includes(item)) {} // Clear intent

// ❌ Bad - prefer-string-starts-ends-with
if (str.substring(0, 6) === 'prefix') {} // Verbose

// ✅ Good
if (str.startsWith('prefix')) {} // Clear intent

Type Safety Best Practices

Rules that promote safer TypeScript patterns and discourage risky operations.

/**
 * Prefer using type parameter when calling Array#reduce
 */
"prefer-reduce-type-parameter": RuleModule;

/**
 * Prefer return this type for methods returning this
 */
"prefer-return-this-type": RuleModule;

/**
 * Prefer using the built-in comparison function in Array.sort()
 */
"require-array-sort-compare": RuleModule;

/**
 * Require that function parameters are used
 */
"no-unused-vars": RuleModule;

/**
 * Disallow unnecessary parameter property assignment
 */
"no-unnecessary-parameter-property-assignment": RuleModule;

/**
 * Prefer readonly arrays and tuples
 */
"prefer-readonly": RuleModule;

/**
 * Prefer readonly parameter types in function declarations
 */
"prefer-readonly-parameter-types": RuleModule;

Usage Examples:

// ❌ Bad - prefer-reduce-type-parameter
const result = items.reduce((acc, item) => acc + item.value, 0);

// ✅ Good
const result = items.reduce<number>((acc, item) => acc + item.value, 0);

// ❌ Bad - require-array-sort-compare
numbers.sort(); // Lexicographic sort, not numeric

// ✅ Good
numbers.sort((a, b) => a - b); // Proper numeric sort

// ❌ Bad - prefer-readonly
function processItems(items: Item[]) {} // Mutable array

// ✅ Good
function processItems(items: readonly Item[]) {} // Immutable array

Error Handling Best Practices

Rules that promote proper error handling and exception management.

/**
 * Require using Error objects as Promise rejection reasons
 */
"prefer-promise-reject-errors": RuleModule;

/**
 * Enforce "throw" expressions to only throw Error objects
 */
"only-throw-error": RuleModule;

/**
 * Require catch clauses to use unknown type for error
 */
"use-unknown-in-catch-callback-variable": RuleModule;

/**
 * Disallow the use of eval()-like functions
 */
"no-implied-eval": RuleModule;

/**
 * Disallow returning await in try/catch/finally
 */
"return-await": RuleModule;

/**
 * Require async functions to have await
 */
"require-await": RuleModule;

Usage Examples:

// ❌ Bad - only-throw-error
throw 'Something went wrong'; // String instead of Error

// ✅ Good
throw new Error('Something went wrong');

// ❌ Bad - use-unknown-in-catch-callback-variable
try {
  riskyOperation();
} catch (error) { // error is implicitly any
  console.log(error.message);
}

// ✅ Good
try {
  riskyOperation();
} catch (error: unknown) {
  if (error instanceof Error) {
    console.log(error.message);
  }
}

// ❌ Bad - prefer-promise-reject-errors
return Promise.reject('Failed'); // String rejection

// ✅ Good
return Promise.reject(new Error('Failed')); // Error object

Function and Method Best Practices

Rules that promote better function and method design patterns.

/**
 * Require promise-returning functions to be async
 */
"promise-function-async": RuleModule;

/**
 * Disallow functions that don't use this
 */
"class-methods-use-this": RuleModule;

/**
 * Require consistent return statements
 */
"consistent-return": RuleModule;

/**
 * Disallow unbound methods
 */
"unbound-method": RuleModule;

/**
 * Require default parameters to be last
 */
"default-param-last": RuleModule;

/**
 * Enforce maximum number of parameters
 */
"max-params": RuleModule;

Usage Examples:

// ❌ Bad - promise-function-async
function fetchData() { // Should be async
  return fetch('/api/data');
}

// ✅ Good
async function fetchData() {
  return fetch('/api/data');
}

// ❌ Bad - unbound-method
const obj = { method() { return this.value; } };
const fn = obj.method; // Lost context

// ✅ Good
const obj = { method() { return this.value; } };
const fn = obj.method.bind(obj); // Bound context

Loop and Iteration Best Practices

Rules that promote efficient and safe iteration patterns.

/**
 * Prefer for-of loops over traditional for loops
 */
"prefer-for-of": RuleModule;

/**
 * Disallow for-in loops over arrays
 */
"no-for-in-array": RuleModule;

/**
 * Prefer Array.find() over filter()[0]
 */
"prefer-find": RuleModule;

/**
 * Disallow function declarations in nested blocks
 */
"no-loop-func": RuleModule;

Usage Examples:

// ❌ Bad - prefer-for-of
for (let i = 0; i < items.length; i++) {
  console.log(items[i]);
}

// ✅ Good
for (const item of items) {
  console.log(item);
}

// ❌ Bad - no-for-in-array
for (const index in array) { // for-in on array
  console.log(array[index]);
}

// ✅ Good
for (const item of array) {
  console.log(item);
}

// ❌ Bad - prefer-find
const user = users.filter(u => u.id === targetId)[0];

// ✅ Good
const user = users.find(u => u.id === targetId);

Type Definition Best Practices

Rules that encourage better type definition practices.

/**
 * Prefer function types over interfaces with call signatures
 */
"prefer-function-type": RuleModule;

/**
 * Prefer literal enum members
 */
"prefer-literal-enum-member": RuleModule;

/**
 * Prefer initializing enum members
 */
"prefer-enum-initializers": RuleModule;

/**
 * Require namespace keyword over module keyword
 */
"prefer-namespace-keyword": RuleModule;

/**
 * Disallow empty interfaces
 */
"no-empty-interface": RuleModule;

/**
 * Require consistent use of type exports
 */
"consistent-type-exports": RuleModule;

Usage Examples:

// ❌ Bad - prefer-function-type
interface Handler {
  (event: Event): void; // Single call signature
}

// ✅ Good
type Handler = (event: Event) => void;

// ❌ Bad - prefer-literal-enum-member
enum Status {
  Active = getValue(), // Computed value
  Inactive = 'inactive'
}

// ✅ Good
enum Status {
  Active = 'active',
  Inactive = 'inactive'
}

// ❌ Bad - no-empty-interface
interface EmptyInterface {} // No members

// ✅ Good
interface UserInterface {
  name: string;
  email: string;
}

Import and Module Best Practices

Rules that promote better module organization and import patterns.

/**
 * Disallow unnecessary type imports
 */
"no-import-type-side-effects": RuleModule;

/**
 * Require consistent type imports
 */
"consistent-type-imports": RuleModule;

/**
 * Require consistent type exports
 */
"consistent-type-exports": RuleModule;

/**
 * Disallow useless empty exports
 */
"no-useless-empty-export": RuleModule;

/**
 * Disallow require statements except in import statements
 */
"no-require-imports": RuleModule;

Usage Examples:

// ❌ Bad - consistent-type-imports
import { User, createUser } from './user'; // Mixed import
const user: User = createUser('John');

// ✅ Good
import type { User } from './user';
import { createUser } from './user';
const user: User = createUser('John');

// ❌ Bad - no-useless-empty-export
export {}; // Unnecessary empty export

// ✅ Good
export type { User };
export { createUser };

Performance Best Practices

Rules that help avoid performance pitfalls and promote efficient code.

/**
 * Prefer regexp exec over string match for global regex
 */
"prefer-regexp-exec": RuleModule;

/**
 * Disallow expressions that evaluate to NaN
 */
"no-loss-of-precision": RuleModule;

/**
 * Require explicit handling of template expression types
 */
"restrict-template-expressions": RuleModule;

/**
 * Require both operands of addition to be numbers or strings
 */
"restrict-plus-operands": RuleModule;

/**
 * Disallow delete operator on array elements
 */
"no-array-delete": RuleModule;

/**
 * Disallow dynamic delete operations
 */
"no-dynamic-delete": RuleModule;

Usage Examples:

// ❌ Bad - no-array-delete
delete array[0]; // Creates hole in array

// ✅ Good
array.splice(0, 1); // Properly removes element

// ❌ Bad - restrict-plus-operands
const result = value + {}; // Unclear concatenation

// ✅ Good
const result = value + String(obj); // Explicit conversion

// ❌ Bad - no-dynamic-delete
delete obj[key]; // Dynamic property deletion

// ✅ Good
const { [key]: _, ...rest } = obj; // Destructuring removal

Configuration Examples

Strict Best Practices

{
  "rules": {
    "@typescript-eslint/prefer-optional-chain": "error",
    "@typescript-eslint/prefer-nullish-coalescing": "error",
    "@typescript-eslint/prefer-as-const": "error",
    "@typescript-eslint/prefer-readonly": "error",
    "@typescript-eslint/require-array-sort-compare": "error",
    "@typescript-eslint/only-throw-error": "error",
    "@typescript-eslint/promise-function-async": "error"
  }
}

Progressive Enhancement

{
  "rules": {
    "@typescript-eslint/prefer-optional-chain": "warn",
    "@typescript-eslint/prefer-includes": "warn",
    "@typescript-eslint/prefer-for-of": "warn",
    "@typescript-eslint/prefer-string-starts-ends-with": "warn",
    "@typescript-eslint/consistent-type-imports": "warn"
  }
}

Types

interface RuleModule {
  meta: {
    type: "problem" | "suggestion" | "layout";
    docs: {
      description: string;
      recommended?: boolean | string;
      requiresTypeChecking?: boolean;
    };
    messages: Record<string, string>;
    schema: JSONSchema;
    fixable?: "code" | "whitespace";
    hasSuggestions?: boolean;
  };
  create(context: RuleContext): RuleListener;
}

interface BestPracticeRuleOptions {
  allowExpressions?: boolean;
  allowTypedFunctionExpressions?: boolean;
  allowHigherOrderFunctions?: boolean;
  allowDirectConstAssertionInArrowFunctions?: boolean;
  allowConciseFunctionExpressionUsage?: boolean;
}

interface PreferOptionalChainOptions {
  checkAny?: boolean;
  checkUnknown?: boolean;
  checkString?: boolean;
  checkNumber?: boolean;
  checkBoolean?: boolean;
  checkBigInt?: boolean;
  requireNullish?: boolean;
}

Install with Tessl CLI

npx tessl i tessl/npm-typescript-eslint--eslint-plugin

docs

best-practices-rules.md

code-quality-rules.md

index.md

plugin-configuration.md

style-formatting-rules.md

type-safety-rules.md

tile.json