Skip to content

Fix ESLint and type-check failures - #76

Merged
Coteh merged 2 commits into
mainfrom
claude/lint-failures-fixes-6fwh4i
Jun 13, 2026
Merged

Coteh merged 2 commits into
mainfrom
claude/lint-failures-fixes-6fwh4i

Conversation

@Coteh

@Coteh Coteh commented Jun 13, 2026 •

Copy link
Copy Markdown
Owner

Summary

Fixes all 92 ESLint errors reported by the failing Code Quality workflow run. After these changes, pnpm lint, pnpm type-check, and pnpm type-check:cypress all pass (the unit test suite and Prettier check remain green as well).

What changed

@ts-ignore → @ts-expect-error (ban-ts-comment)

  • Converted directives that suppress a real type error across commands.ts, animation.ts, undo.ts, storage/cli.ts, cli_storage_test.ts, and vite.config.ts.
  • Removed directives that were no longer suppressing anything (how-to-play, the Sentry beforeSend handler, and a dead import.meta directive in game.ts) — converting these would have produced unused directive type errors instead.

Replace any with real types (no-explicit-any)

  • Introduced a GameEventData type for the game EventHandler payload.
  • Made getPreferenceValue generic (defaulting to unknown) so call sites infer the right type, and typed the Preferences index signature / savePreferenceValue value as unknown.
  • Narrowed catch clauses (share/browser.ts, index.ts) instead of typing the error as any.
  • Typed the mock Storage.setItem value as string.

Other rule fixes

  • no-unsafe-function-type: replaced Function with () => void in the prompt-dialog options.
  • prefer-const / no-var: applied across index.ts, asset.ts, snow.ts, etc. (mostly via eslint --fix).
  • no-useless-assignment: scoped the enabled flag into the branch that uses it.
  • preserve-caught-error: attached { cause: err } to the re-thrown error in the file-transformer plugin.
  • Removed an unused constant and tidied unused parameters / catch bindings (no-unused-vars).

Scoped ESLint overrides (eslint.config.mjs)

  • __mocks__/**/*.js: allow CommonJS require/module.exports for the Jest fs mock.
  • cypress/**/*.ts: disable no-unused-expressions (Chai assertions like expect(x).to.be.true) and no-explicit-any (Cypress Chainable<any> command declarations).

Testing

  • pnpm lint — 0 errors
  • pnpm type-check — passes
  • pnpm type-check:cypress — passes
  • pnpm run test-ci — 48/48 passing
  • pnpm format:check — clean

https://claude.ai/code/session_016gBdoTccTGigXLvLMMS38W


Generated by Claude Code

Summary by CodeRabbit

  • Refactor

    • Strengthened TypeScript type safety across codebase, converting broad any types to unknown and introducing explicit type signatures.
    • Improved error handling with more descriptive error messages and context preservation.
    • Modernized variable declarations and code patterns for better maintainability.
  • Tests

    • Enhanced test code typing and safety.

Resolve all 92 ESLint errors reported by the Code Quality workflow:

- Convert active @ts-ignore directives to @ts-expect-error, and drop
  the ones that were no longer suppressing a real type error
- Replace explicit `any` with proper types (GameEventData event payload,
  generic getPreferenceValue, narrowed catch clauses, Storage.setItem)
- Replace the `Function` type in render dialog options with `() => void`
- Apply prefer-const / no-var fixes (including snow.ts and asset.ts)
- Attach `cause` to the re-thrown error in the file-transformer plugin
- Remove an unused constant and tidy unused parameters/catch bindings
- Add scoped ESLint overrides for CommonJS Jest mocks and Cypress specs
  (Chai assertions and `any`-typed command declarations)
@coderabbitai

coderabbitai Bot commented Jun 13, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Coteh, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 32 minutes and 55 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7820dc6e-3fb5-47de-bfcb-e22e0515bd3b

📥 Commits

Reviewing files that changed from the base of the PR and between 4312204 and 61faa4e.

📒 Files selected for processing (4)
  • src/index.ts
  • src/manager/animation.ts
  • src/storage/cli.ts
  • vite.config.ts
📝 Walkthrough

Walkthrough

This PR systematically improves TypeScript type safety and code quality across the codebase. The core change introduces a typed GameEventData structure for event payloads, which cascades into tighter type signatures throughout. Supporting improvements include replacing any with unknown, enhancing error handling with proper casting, modernizing TypeScript directives, and converting variable bindings to use const/let.

Changes

Type Safety and Code Quality Improvements

Layer / File(s) Summary
Event System Type Contract
src/game.ts, src/index.ts
New exported GameEventData type describes event payloads with typed gameState, persistentState, and immutable undoInfo.undoStack. EventHandler signature changes from (eventID: string, data?: any) to (eventID: string, data?: GameEventData). Event consumer in index.ts uses optional chaining and non-null assertions with the typed data structure.
Data Type Tightening and Error Handling
src/preferences.ts, src/render.ts, src/share/browser.ts, src/index.ts, plugins/file-transformer.ts, plugins/app-labels.ts, test/browser_storage_test.ts
Preferences index signature narrows from any to unknown; getPreferenceValue becomes generic getPreferenceValue<T = unknown>(key). PromptDialogOptions callbacks tightened from Function to () => void. Error handling improved with type casting (navigator.share and game initialization). File transformer error now includes input path and attaches original error as cause. Unused error parameters marked with underscore.
TypeScript Directive Modernization
cypress/support/commands/commands.ts, src/manager/animation.ts, src/manager/undo.ts, src/storage/cli.ts, vite.config.ts, src/component/how-to-play/index.ts, test/cli_storage_test.ts
Generic @ts-ignore replaced with targeted @ts-expect-error throughout. Unnecessary suppression comments removed from component rendering calls where type inference is sufficient.
Modern Variable Bindings and Build Configuration
src/game.ts, src/manager/asset.ts, vendor/snow.ts, test/cli_storage_test.ts, cypress.config.ts, eslint.config.mjs
Variables converted from var to block-scoped let/const for improved scoping. debugEnabled made immutable; snowflake generation uses local constants. ESLint config adds overrides for CommonJS jest mocks (__mocks__/**/*.js) and Cypress TypeScript specs. Cypress config marks unused parameter with underscore.
UI Wiring Refinements
src/index.ts
snowEmbed DOM reference converted to const. Settings handler simplified by removing intermediate enabled variable and inlining animation toggle. Block style selection uses nextBlockStyle constant. Tileset preferences explicitly typed as Record<string, string>. Obsolete Sentry @ts-ignore comment removed.

🎯 2 (Simple) | ⏱️ ~12 minutes

🐰 A hop toward safety so bright,
With types now tight and bindings right,
No more any to confuse the code,
Just unknown and const on the road,
Better errors light the way.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix ESLint and type-check failures' directly and clearly describes the primary objective of the PR, which is resolving ESLint errors and TypeScript type-checking issues across the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/lint-failures-fixes-6fwh4i

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 13, 2026 •

Copy link
Copy Markdown

Deploying 2048-clone with  Cloudflare Pages  Cloudflare Pages

Latest commit: 61faa4e
Status: ✅  Deploy successful!
Preview URL: https://05f5d0c3.2048-clone-33h.pages.dev
Branch Preview URL: https://claude-lint-failures-fixes-6.2048-clone-33h.pages.dev

View logs

@github-actions

github-actions Bot commented Jun 13, 2026 •

Copy link
Copy Markdown

Test Results

 14 files  ±0   45 suites  ±0   2m 45s ⏱️ -1s
173 tests ±0  173 ✅ ±0  0 💤 ±0  0 ❌ ±0 
181 runs  ±0  181 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 61faa4e. ± Comparison against base commit 789633c.

♻️ This comment has been updated with latest results.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/index.ts (1)

564-574: 💤 Low value

The enabled constant declaration is redundant.

The pattern const enabled = (isAnimationEnabled = !isAnimationEnabled); works correctly but introduces an unnecessary intermediate variable. Since enabled is only used in the immediately following if statement, you can simplify by checking isAnimationEnabled directly.

♻️ Proposed simplification
 } else if (elem.classList.contains(ANIMATIONS_SETTING_NAME)) {
     const knob = setting.querySelector(".knob") as HTMLElement;
-    const enabled = (isAnimationEnabled = !isAnimationEnabled);
+    isAnimationEnabled = !isAnimationEnabled;
     animationManager.isAnimationEnabled = isAnimationEnabled;
     savePreferenceValue(
         ANIMATIONS_PREFERENCE_NAME,
         isAnimationEnabled ? SETTING_ENABLED : SETTING_DISABLED,
     );
-    if (enabled) {
+    if (isAnimationEnabled) {
         knob.classList.add("enabled");
     } else {
         knob.classList.remove("enabled");
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/index.ts` around lines 564 - 574, The const enabled variable is
redundant; update the toggle logic in the click handler so you flip
isAnimationEnabled directly and use it in the branch: set isAnimationEnabled =
!isAnimationEnabled, assign animationManager.isAnimationEnabled =
isAnimationEnabled, call savePreferenceValue(ANIMATIONS_PREFERENCE_NAME,
isAnimationEnabled ? SETTING_ENABLED : SETTING_DISABLED), and then use if
(isAnimationEnabled) { knob.classList.add("enabled"); } else {
knob.classList.remove("enabled"); } (remove the const enabled declaration).
src/manager/animation.ts (1)

19-24: ⚡ Quick win

Consider using definite assignment assertion instead of suppression.

While the directive normalization is good, TypeScript's definite assignment assertion operator (!) is a cleaner solution for fields initialized via method calls:

-    // `@ts-expect-error` TODO: This field is assigned in the constructor via resetState but TS is not smart enough to realize that
-    public newBlocks: Position[];
-    // `@ts-expect-error` TODO: This field is assigned in the constructor via resetState but TS is not smart enough to realize that
-    public movedBlocks: (Position | undefined)[][];
-    // `@ts-expect-error` TODO: This field is assigned in the constructor via resetState but TS is not smart enough to realize that
-    public mergedBlocks: MergedBlock[];
+    public newBlocks!: Position[];
+    public movedBlocks!: (Position | undefined)[][];
+    public mergedBlocks!: MergedBlock[];

This tells TypeScript you guarantee initialization without suppressing potential type errors in the field usage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/manager/animation.ts` around lines 19 - 24, Replace the three "//
`@ts-expect-error`" suppressions on the class fields newBlocks, movedBlocks, and
mergedBlocks with TypeScript definite assignment assertions (append "!" to the
property names) so they read "public newBlocks!: Position[];", "public
movedBlocks!: (Position | undefined)[][];", and "public mergedBlocks!:
MergedBlock[];"; remove the corresponding ts-expect-error lines and keep
resetState as the constructor/initializer that guarantees these fields are set.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/storage/cli.ts`:
- Around line 74-76: CLIGameStorage.loadFile incorrectly passes a Buffer to
JSON.parse (and suppresses the TS error); update the code in
CLIGameStorage.loadFile to read text not a Buffer (e.g.,
fs.readFileSync(filename, "utf8")) or call .toString("utf8") on the returned
Buffer, remove the `@ts-expect-error`, and then JSON.parse the resulting string;
apply the same change to any other CLI storage file-read sites that parse JSON
from disk to avoid Buffer-to-string type mismatches.

In `@vite.config.ts`:
- Around line 28-29: Replace the incorrect numeric literal and suppressed error
on the terser options: in the terserOptions object (property ecma) change ecma:
6 to a valid Terser ECMA year such as ecma: 2015 and remove the preceding "//
`@ts-expect-error` TODO..." comment so the TypeScript type is satisfied without
suppression.

---

Nitpick comments:
In `@src/index.ts`:
- Around line 564-574: The const enabled variable is redundant; update the
toggle logic in the click handler so you flip isAnimationEnabled directly and
use it in the branch: set isAnimationEnabled = !isAnimationEnabled, assign
animationManager.isAnimationEnabled = isAnimationEnabled, call
savePreferenceValue(ANIMATIONS_PREFERENCE_NAME, isAnimationEnabled ?
SETTING_ENABLED : SETTING_DISABLED), and then use if (isAnimationEnabled) {
knob.classList.add("enabled"); } else { knob.classList.remove("enabled"); }
(remove the const enabled declaration).

In `@src/manager/animation.ts`:
- Around line 19-24: Replace the three "// `@ts-expect-error`" suppressions on the
class fields newBlocks, movedBlocks, and mergedBlocks with TypeScript definite
assignment assertions (append "!" to the property names) so they read "public
newBlocks!: Position[];", "public movedBlocks!: (Position | undefined)[][];",
and "public mergedBlocks!: MergedBlock[];"; remove the corresponding
ts-expect-error lines and keep resetState as the constructor/initializer that
guarantees these fields are set.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 19be4bb6-74dd-4316-9a95-49f4de4fcb1d

📥 Commits

Reviewing files that changed from the base of the PR and between 789633c and 4312204.

📒 Files selected for processing (19)
  • cypress.config.ts
  • cypress/support/commands/commands.ts
  • eslint.config.mjs
  • plugins/app-labels.ts
  • plugins/file-transformer.ts
  • src/component/how-to-play/index.ts
  • src/game.ts
  • src/index.ts
  • src/manager/animation.ts
  • src/manager/asset.ts
  • src/manager/undo.ts
  • src/preferences.ts
  • src/render.ts
  • src/share/browser.ts
  • src/storage/cli.ts
  • test/browser_storage_test.ts
  • test/cli_storage_test.ts
  • vendor/snow.ts
  • vite.config.ts
💤 Files with no reviewable changes (1)
  • src/component/how-to-play/index.ts

Comment thread src/storage/cli.ts Outdated
Comment thread vite.config.ts Outdated
- cli.ts: read state files as UTF-8 text so JSON.parse receives a string,
  removing the Buffer-related @ts-expect-error
- vite.config.ts: use a valid Terser ECMA year (2015) instead of `6`,
  removing the @ts-expect-error
- animation.ts: use definite assignment assertions for fields initialized
  via resetState() instead of @ts-expect-error suppressions
- index.ts: drop the redundant `enabled` local and branch on
  isAnimationEnabled directly
@Coteh
Coteh merged commit 9753cb5 into main Jun 13, 2026
8 checks passed
@Coteh
Coteh deleted the claude/lint-failures-fixes-6fwh4i branch June 13, 2026 18:24
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.

2 participants