Skip to content

Enable remaining readability lint rules in cleanup batches #80504

@steipete

Description

@steipete

Follow-up from the May 2026 lint hardening pass. The easy zero-drift Vitest rules are already enabled, but the remaining readability rules create too much cleanup churn for the same commit.

Measured with:

node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.json \
  -D eslint/no-implicit-coercion \
  -D eslint/object-shorthand \
  -D eslint/prefer-object-has-own \
  -D typescript/no-import-type-side-effects \
  -D typescript/non-nullable-type-assertion-style \
  -D typescript/use-unknown-in-catch-callback-variable \
  -D typescript/require-await \
  -D unicorn/explicit-length-check \
  -D unicorn/no-useless-undefined \
  -D unicorn/no-zero-fractions \
  -D unicorn/prefer-string-replace-all \
  src ui packages extensions scripts

Probe counts:

  • eslint/object-shorthand: 66 hits
  • unicorn/no-zero-fractions: 52 hits
  • typescript/no-import-type-side-effects: 101 hits
  • eslint/no-implicit-coercion: 101 hits
  • eslint/prefer-object-has-own: 183 hits
  • unicorn/explicit-length-check: 278 hits
  • typescript/use-unknown-in-catch-callback-variable: 412 hits
  • unicorn/prefer-string-replace-all: 1416 hits
  • unicorn/no-useless-undefined: 5041 hits
  • typescript/require-await: 10050 hits

Suggested path:

  1. Enable the small readability batch first:
    • eslint/object-shorthand
    • unicorn/no-zero-fractions
    • typescript/no-import-type-side-effects
    • eslint/no-implicit-coercion
    • eslint/prefer-object-has-own
  2. Consider unicorn/explicit-length-check separately if the explicit style is desired.
  3. Consider typescript/use-unknown-in-catch-callback-variable separately; useful, but touches many async error paths.
  4. Defer or skip the very noisy rules unless doing dedicated cleanup-only work:
    • unicorn/prefer-string-replace-all
    • unicorn/no-useless-undefined
    • typescript/require-await

Examples:

// object-shorthand
{ getRuntimeConfig: getRuntimeConfig }
{ getRuntimeConfig }

// no-zero-fractions
cost: { input: 3.0, output: 7.0 }
cost: { input: 3, output: 7 }

// no-import-type-side-effects
import { type ResolverContext, type SecretDefaults } from "./runtime-shared.js";
import type { ResolverContext, SecretDefaults } from "./runtime-shared.js";

// no-implicit-coercion
if (!!entries && typeof entries === "object") {}
if (Boolean(entries) && typeof entries === "object") {}

// prefer-object-has-own
Object.prototype.hasOwnProperty.call(cursor, segment)
Object.hasOwn(cursor, segment)

// explicit-length-check
while (stack.length && stack.at(-1)?.end === pos) {}
while (stack.length > 0 && stack.at(-1)?.end === pos) {}

// use-unknown-in-catch-callback-variable
loop().catch((err) => String(err));
loop().catch((err: unknown) => String(err));

Metadata

Metadata

Assignees

No one assigned

    Labels

    maintainerMaintainer-authored PRtriage: refactor-onlyCandidate: refactor/cleanup-only PR without maintainer context.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions