-
Notifications
You must be signed in to change notification settings - Fork 509
Enabled the @typescript-eslint/no-unused-expressions
eslint rule
#2014
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughRemoved an explicit disable of Changes
Sequence Diagram(s)sequenceDiagram
participant U as User
participant Main as Main.ts
participant Registry as Modal Registry
participant Modal as Specific Modal
U->>Main: request open modal
Main->>Registry: lookup modal element
alt element exists && instanceof expected
Main->>Modal: show()/open()
else missing or wrong type
Main->>Main: console.warn("Modal missing or wrong type")
end
sequenceDiagram
participant Row as EventsDisplay Row
participant Bus as EventBus
Row->>Row: user clicks
alt event.focusID present
Row->>Bus: emit GoToPlayerEvent(focusID)
end
alt event.unitView present
Row->>Bus: emit GoToUnitEvent(unitView)
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Assessment against linked issues
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the 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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🧹 Nitpick comments (3)
src/client/graphics/layers/EventsDisplay.ts (1)
1038-1051
: Drop redundant inner checks in onClick closuresYou already branch on
event.focusID
/event.unitView
above. The innerif
adds noise without safety.- onClick: () => { - if (event.focusID) - this.emitGoToPlayerEvent(event.focusID); - }, + onClick: () => + this.emitGoToPlayerEvent(event.focusID!), ... - onClick: () => { - if (event.unitView) - this.emitGoToUnitEvent( - event.unitView, - ); - }, + onClick: () => + this.emitGoToUnitEvent(event.unitView!),If you prefer to avoid non-null assertions, capture into a const before the template map.
src/client/Main.ts (2)
108-111
: Avoid unsafe cast; rely on runtime narrowingCasting to
NewsModal
and then checkinginstanceof
is redundant and can hide null at compile time.- const newsModal = document.querySelector("news-modal") as NewsModal; - if (!newsModal || !(newsModal instanceof NewsModal)) { + const newsModal = document.querySelector("news-modal"); + if (!(newsModal instanceof NewsModal)) { console.warn("News modal element not found"); }
96-430
: Reduce repetition: introduce a tiny helper to fetch-and-narrow custom elementsYou repeat “query + instanceof + warn” many times. A small helper improves readability and safety.
function getEl<T extends Element>( selector: string, Ctor: abstract new (...args: any[]) => T, name: string, ): T | null { const el = document.querySelector(selector); if (el instanceof Ctor) return el; console.warn(`${name} element not found`); return null; } // Usage const spModal = getEl("single-player-modal", SinglePlayerModal, "Singleplayer modal"); const hlpModal = getEl("help-modal", HelpModal, "Help modal");This keeps code clean and idiomatic TS without extra libs.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
eslint.config.js
(1 hunks)src/client/Main.ts
(10 hunks)src/client/graphics/layers/EventsDisplay.ts
(2 hunks)src/core/execution/RailroadExecution.ts
(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-09T02:20:43.637Z
Learnt from: VariableVince
PR: openfrontio/OpenFrontIO#1110
File: src/client/Main.ts:293-295
Timestamp: 2025-06-09T02:20:43.637Z
Learning: In src/client/Main.ts, during game start in the handleJoinLobby callback, UI elements are hidden using direct DOM manipulation with classList.add("hidden") for consistency. This includes modals, buttons, and error divs. The codebase follows this pattern rather than using component APIs for hiding elements during game transitions.
Applied to files:
src/client/Main.ts
🔇 Additional comments (2)
src/core/execution/RailroadExecution.ts (1)
167-169
: Guardunit
access to avoid runtime errors
Replace direct calls with local variables and optional chaining:- if (this.railRoad.from.unit.isActive()) this.railRoad.from.unit.touch(); - if (this.railRoad.to.unit.isActive()) this.railRoad.to.unit.touch(); + const fromUnit = this.railRoad.from.unit; + if (fromUnit?.isActive()) fromUnit.touch(); + const toUnit = this.railRoad.to.unit; + if (toUnit?.isActive()) toUnit.touch();If
unit
is always non-null here by contract, you can omit the?.
checks and treat this as a nit. Otherwise, keep the guards.src/client/Main.ts (1)
575-577
: Nice: explicit guard before showing starting modalClear and robust. Matches the lint rule’s intent.
9340f8f
to
e701dc9
Compare
e701dc9
to
36bd029
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (8)
src/client/Main.ts (8)
166-171
: Still unsafe: spModal.open() can run when element is missingYou warn but the click handler calls
open()
unguarded. This can crash at runtime.Minimal, typesafe fix:
- const spModal = document.querySelector( - "single-player-modal", - ) as SinglePlayerModal; + const spModal = document.querySelector( + "single-player-modal", + ) as SinglePlayerModal | null; @@ - if (this.usernameInput?.isValid()) { - spModal.open(); - } + if (this.usernameInput?.isValid()) { + spModal?.open(); + }Also applies to: 175-179
187-190
: Same pattern: hlpModal.open() unguardedThe click handler can call
open()
on a missing element.- const hlpModal = document.querySelector("help-modal") as HelpModal; + const hlpModal = document.querySelector("help-modal") as HelpModal | null; @@ - helpButton.addEventListener("click", () => { - hlpModal.open(); - }); + helpButton.addEventListener("click", () => hlpModal?.open());Also applies to: 193-195
197-203
: Same pattern: flagInputModal.open() unguardedCan throw when the element is absent.
- const flagInputModal = document.querySelector( - "flag-input-modal", - ) as FlagInputModal; + const flagInputModal = document.querySelector( + "flag-input-modal", + ) as FlagInputModal | null; @@ - flgInput.addEventListener("click", () => { - flagInputModal.open(); - }); + flgInput.addEventListener("click", () => flagInputModal?.open());Also applies to: 206-208
210-218
: Immediate usages of patternsModal can crash; return early after warnYou set properties and call methods right after a warn, which will throw if the element is missing or wrong type. Early-return keeps later code safe.
- this.patternsModal = document.querySelector( + this.patternsModal = document.querySelector( "territory-patterns-modal", ) as TerritoryPatternsModal; if ( !this.patternsModal || !(this.patternsModal instanceof TerritoryPatternsModal) ) { console.warn("Territory patterns modal element not found"); + return; }Also applies to: 224-228
230-238
: tokenLoginModal is used later without checks
this.tokenLoginModal.open(token)
in hash handlers will throw if the element is missing.Two small, local fixes:
- this.tokenLoginModal = document.querySelector( - "token-login", - ) as TokenLoginModal; + this.tokenLoginModal = document.querySelector( + "token-login", + ) as TokenLoginModal | null;- this.tokenLoginModal.open(token); + if (this.tokenLoginModal instanceof TokenLoginModal) { + this.tokenLoginModal.open(token); + } else { + console.warn("Token login modal element not found"); + }- this.tokenLoginModal.open(token); + if (this.tokenLoginModal instanceof TokenLoginModal) { + this.tokenLoginModal.open(token); + } else { + console.warn("Token login modal element not found"); + }Also applies to: 478-479, 496-498
346-351
: settingsModal.open() should be guarded at bind timeAttach the listener only when the element is valid.
- const settingsModal = document.querySelector( - "user-setting", - ) as UserSettingModal; - if (!settingsModal || !(settingsModal instanceof UserSettingModal)) { - console.warn("User settings modal element not found"); - } - document - .getElementById("settings-button") - ?.addEventListener("click", () => { - settingsModal.open(); - }); + const settingsEl = document.querySelector("user-setting"); + if (settingsEl instanceof UserSettingModal) { + document.getElementById("settings-button")?.addEventListener("click", () => { + settingsEl.open(); + }); + } else { + console.warn("User settings modal element not found"); + }Also applies to: 352-356
358-363
: hostModal.open() should be guardedSame issue:
open()
called even if element is missing.- const hostModal = document.querySelector( - "host-lobby-modal", - ) as HostPrivateLobbyModal; - if (!hostModal || !(hostModal instanceof HostPrivateLobbyModal)) { - console.warn("Host private lobby modal element not found"); - } + const hostModal = document.querySelector("host-lobby-modal"); + if (!(hostModal instanceof HostPrivateLobbyModal)) { + console.warn("Host private lobby modal element not found"); + } @@ - hostModal.open(); + if (hostModal instanceof HostPrivateLobbyModal) hostModal.open();Also applies to: 366-371
373-378
: joinModal is assumed present later; enforce invariant or guard usesDownstream code calls
open()
/close()
without checks. Fail fast to keep the property non-null, or make it nullable and guard every use (more churn). Recommend fail-fast.- this.joinModal = document.querySelector( + this.joinModal = document.querySelector( "join-private-lobby-modal", ) as JoinPrivateLobbyModal; - if (!this.joinModal || !(this.joinModal instanceof JoinPrivateLobbyModal)) { - console.warn("Join private lobby modal element not found"); - } + if (!(this.joinModal instanceof JoinPrivateLobbyModal)) { + throw new Error("JoinPrivateLobbyModal element not found"); + }Also applies to: 385-388
🧹 Nitpick comments (2)
src/client/Main.ts (2)
107-111
: Simplify the guard and avoid unsafeas
cast
newsModal ||
is redundant;null instanceof NewsModal
is already false. Also prefer runtime-safe narrowing withoutas
.- const newsModal = document.querySelector("news-modal") as NewsModal; - if (!newsModal || !(newsModal instanceof NewsModal)) { + const newsEl = document.querySelector("news-modal"); + if (!(newsEl instanceof NewsModal)) { console.warn("News modal element not found"); }
575-577
: LGTM: safe show for GameStartingModalGood guard; avoids calling
show()
on a wrong/missing element. Minor nit:instanceof
already handles null, so the leading truthy check is redundant.- if (startingModal && startingModal instanceof GameStartingModal) { + if (startingModal instanceof GameStartingModal) { startingModal.show(); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/client/Main.ts
(10 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Michal-Martinek
PR: openfrontio/OpenFrontIO#2014
File: eslint.config.js:43-43
Timestamp: 2025-09-06T07:10:42.249Z
Learning: When analyzing potential no-unused-expressions violations, always examine the full context. Expressions used in template literals, filter predicates, assignments, or other consuming contexts are not violations even if they use short-circuit operators like &&.
Learnt from: Michal-Martinek
PR: openfrontio/OpenFrontIO#2014
File: eslint.config.js:43-43
Timestamp: 2025-09-06T07:10:42.248Z
Learning: The `typescript-eslint/no-unused-expressions` ESLint rule only flags standalone expression statements that don't consume their results or have side effects. Expressions that are part of return statements, assignments, or other consuming contexts are not violations of this rule.
📚 Learning: 2025-06-09T02:20:43.637Z
Learnt from: VariableVince
PR: openfrontio/OpenFrontIO#1110
File: src/client/Main.ts:293-295
Timestamp: 2025-06-09T02:20:43.637Z
Learning: In src/client/Main.ts, during game start in the handleJoinLobby callback, UI elements are hidden using direct DOM manipulation with classList.add("hidden") for consistency. This includes modals, buttons, and error divs. The codebase follows this pattern rather than using component APIs for hiding elements during game transitions.
Applied to files:
src/client/Main.ts
content: this.getEventDescription(event), | ||
onClick: () => { | ||
event.focusID && | ||
if (event.focusID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the related to the no-unused-expressions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, otherwise linter complaints because result of this expression is not used.
1038:39 error Expected an assignment or function call and instead saw an expression @typescript-eslint/no-unused-expressions
Description:
@typescript-eslint/no-unused-expressions
eslint rule #1790&&
changed to properif
statementsA instanceof B;
expressions now emit warningsPlease complete the following:
Please put your Discord username so you can be contacted if a bug or regression is found:
DISCORD_USERNAME
michal7952