Skip to content

feat(ts): implement unnecessaryConstructors rule#2953

Closed
jcamino wants to merge 3 commits into
flint-fyi:mainfrom
jcamino:port/2226-unnecessaryConstructors
Closed

feat(ts): implement unnecessaryConstructors rule#2953
jcamino wants to merge 3 commits into
flint-fyi:mainfrom
jcamino:port/2226-unnecessaryConstructors

Conversation

@jcamino

@jcamino jcamino commented Jun 10, 2026

Copy link
Copy Markdown

PR Checklist

Overview

Draft port — opening for maintainer review, not asserting merge-readiness.

Implements ts/unnecessaryConstructors, the flint equivalent of @typescript-eslint/no-useless-constructor.
Reports constructors that are equivalent to the implicit default constructor — an empty constructor in a base class, or a derived-class constructor that only forwards its parameters to super — with a suggestion to remove them.

Provenance (staged commits)

Ported from typescript-eslint/typescript-eslint@4ba3e02e (75 LOC):

  1. verbatim upstream copy → 2. flint scaffolding match → 3. implementation.
    Diff commits 1→3 to see exactly what the port changed.

Note on sources: the upstream rule is an extension rule that delegates its core logic to ESLint core's no-useless-constructor via getESLintCoreRule. Since flint rules are self-contained, this port merges the core semantics and the TS-specific exemptions (accessibility modifiers, parameter properties, parameter decorators) into one rule; both upstream test suites were used as the edge-case reference.

Behavior vs upstream

  • Rest parameter with a destructuring pattern (constructor(...[a, b]) { super(...arguments); }): ESLint core treats any rest element as "simple" and reports; this port requires the rest parameter to be a plain identifier and does not report. Removing such a constructor can change behavior (pattern defaults may have side effects), so the port takes the safe direction.
  • Suggestion ASI guard simplified: core uses its general-purpose needsPrecedingSemicolon machinery to decide whether removing the constructor needs a separating ;; this port uses class-member-shaped checks (previous member ends in an unterminated initializer, next member begins with [/*/in/instanceof). Output is identical across core's suggestion test matrix (all ported); the only known delta inserts a harmless extra ; in one TS-specific corner.
  • Core's removeConstructor suggestion is ported as a real flint suggestion, not dropped.

Everything else is behavior parity, including: overload signatures / ambient declarations never flagged, implements-only classes treated as base classes, 'constructor'() string-key form flagged, and parentheses skipped at all expression positions.

A courtesy note: rule naming for the unnecessary* family is under discussion in #2802 — happy to rename if that lands on a different convention.

Files

  • packages/ts/src/rules/unnecessaryConstructors.ts — the rule (self-contained port)
  • packages/ts/src/rules/unnecessaryConstructors.test.ts — 25 invalid cases (snapshot + suggestion output each) + 43 valid cases
  • packages/site/src/content/docs/rules/ts/unnecessaryConstructors.mdx — full rule doc
  • packages/ts/src/plugin.ts — rule registered alphabetically
  • packages/comparisons/src/data.json — existing entry marked "status": "implemented"
  • .changeset/unnecessary-constructors.md — patch changeset

Local gates

eslint --max-warnings 0 · tsc -b packages/ts · vitest (rule test, 68 passing) · vitest (comparisons) · prettier --check — all pass locally.

🤖 Generated with Claude Code

jcamino and others added 3 commits June 10, 2026 14:29
…ypescript-eslint

Verbatim copy of typescript-eslint/typescript-eslint@4ba3e02 (rule, tests, docs) as the starting point for the flint unnecessaryConstructors port. Subsequent commits adapt it to flint; diff them to see exactly what the port changed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Stage 2 of the port: reshape the upstream files to flint's rule/test/docs conventions (ruleCreator, .ts specifiers, rule-tester format, mdx frontmatter) before the full implementation pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ports @typescript-eslint/no-useless-constructor (merging its ESLint-core base-rule logic) to flint's ruleCreator/services API. Includes rule, tests, docs, comparisons status, and a changeset. fixes flint-fyi#2226

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@netlify

netlify Bot commented Jun 10, 2026

Copy link
Copy Markdown

Deploy Preview for flint-fyi ready!

Name Link
🔨 Latest commit 78db072
🔍 Latest deploy log https://app.netlify.com/projects/flint-fyi/deploys/6a29b4e9307d6300082383ef
😎 Deploy Preview https://deploy-preview-2953--flint-fyi.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@changeset-bot

changeset-bot Bot commented Jun 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 78db072

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@flint.fyi/ts Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🚀 Feature: Implement unnecessaryConstructors rule (TypeScript)

2 participants