Enable @typescript eslint/prefer nullish coalescing eslint rule (#1420)

## Description:

Fixes #952 
Enabled @typescript-eslint/prefer-nullish-coalescing rule and worked
through every error, introducing ?? and ??= operators or disabling
errors with inline comments where appropriate, to the best of my
ability.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I understand that submitting code with bugs that could have been
caught through manual testing blocks releases and new features for all
contributors

## Please put your Discord username so you can be contacted if a bug or
regression is found:

g_santos_m
This commit is contained in:
g-santos-m
2025-07-15 05:00:06 +02:00
committed by GitHub
parent ac9a9ec253
commit 31381f67f4
28 changed files with 95 additions and 85 deletions
+2 -2
View File
@@ -99,7 +99,7 @@ export class LangSelector extends LitElement {
private async initializeLanguage() {
const browserLocale = navigator.language;
const savedLang = localStorage.getItem("lang");
const userLang = this.getClosestSupportedLang(savedLang || browserLocale);
const userLang = this.getClosestSupportedLang(savedLang ?? browserLocale);
this.defaultTranslations = this.loadLanguage("en");
this.translations = this.loadLanguage(userLang);
@@ -110,7 +110,7 @@ export class LangSelector extends LitElement {
}
private loadLanguage(lang: string): Record<string, string> {
const language = this.languageMap[lang] || {};
const language = this.languageMap[lang] ?? {};
const flat = flattenTranslations(language);
return flat;
}
+1 -1
View File
@@ -110,7 +110,7 @@ export class PublicLobby extends LitElement {
const teamCount =
lobby.gameConfig.gameMode === GameMode.Team
? lobby.gameConfig.playerTeams || 0
? (lobby.gameConfig.playerTeams ?? 0)
: null;
const mapImageSrc = this.mapImages.get(lobby.gameID);
+8 -10
View File
@@ -245,16 +245,14 @@ export class Transport {
}
private startPing() {
if (this.isLocal || this.pingInterval) return;
if (this.pingInterval === null) {
this.pingInterval = window.setInterval(() => {
if (this.socket !== null && this.socket.readyState === WebSocket.OPEN) {
this.sendMsg({
type: "ping",
} satisfies ClientPingMessage);
}
}, 5 * 1000);
}
if (this.isLocal) return;
this.pingInterval ??= window.setInterval(() => {
if (this.socket !== null && this.socket.readyState === WebSocket.OPEN) {
this.sendMsg({
type: "ping",
} satisfies ClientPingMessage);
}
}, 5 * 1000);
}
private stopPing() {
+1 -1
View File
@@ -172,7 +172,7 @@ export function getAltKey(): string {
export function getGamesPlayed(): number {
try {
return parseInt(localStorage.getItem("gamesPlayed") || "0", 10) || 0;
return parseInt(localStorage.getItem("gamesPlayed") ?? "0", 10) || 0;
} catch (error) {
console.warn("Failed to read games played from localStorage:", error);
return 0;
+2 -2
View File
@@ -91,9 +91,9 @@ const getSpriteForUnit = (unit: UnitView): ImageBitmap | null => {
const unitType = unit.type();
if (unitType === UnitType.Train) {
const trainType = trainTypeToSpriteType(unit);
return spriteMap.get(trainType) || null;
return spriteMap.get(trainType) ?? null;
}
return spriteMap.get(unitType) || null;
return spriteMap.get(unitType) ?? null;
};
export const isSpriteReady = (unit: UnitView): boolean => {
+1 -1
View File
@@ -137,7 +137,7 @@ export class EventsDisplay extends LitElement implements Layer {
}
private toggleEventFilter(filterName: MessageCategory) {
const currentState = this.eventsFilters.get(filterName) || false;
const currentState = this.eventsFilters.get(filterName) ?? false;
this.eventsFilters.set(filterName, !currentState);
this.requestUpdate();
}
+8 -8
View File
@@ -298,14 +298,14 @@ export class RadialMenu implements Layer {
const disabled = this.params === null || d.data.disabled(this.params);
const color = disabled
? this.config.disabledColor
: d.data.color || "#333333";
: (d.data.color ?? "#333333");
const opacity = disabled ? 0.5 : 0.7;
if (d.data.id === this.selectedItemId && this.currentLevel > level) {
return color;
}
return d3.color(color)?.copy({ opacity: opacity })?.toString() || color;
return d3.color(color)?.copy({ opacity: opacity })?.toString() ?? color;
})
.attr("stroke", "#ffffff")
.attr("stroke-width", "2")
@@ -341,7 +341,7 @@ export class RadialMenu implements Layer {
const color =
this.params === null || d.data.disabled(this.params)
? this.config.disabledColor
: d.data.color || "#333333";
: (d.data.color ?? "#333333");
path.attr("fill", color);
}
});
@@ -405,11 +405,11 @@ export class RadialMenu implements Layer {
path.attr("stroke-width", "2");
const color = disabled
? this.config.disabledColor
: d.data.color || "#333333";
: (d.data.color ?? "#333333");
const opacity = disabled ? 0.5 : 0.7;
path.attr(
"fill",
d3.color(color)?.copy({ opacity: opacity })?.toString() || color,
d3.color(color)?.copy({ opacity: opacity })?.toString() ?? color,
);
};
@@ -625,7 +625,7 @@ export class RadialMenu implements Layer {
this.selectedItemId = null;
}
this.currentMenuItems = previousItems || [];
this.currentMenuItems = previousItems ?? [];
if (this.currentLevel === 0) {
this.updateCenterButtonState("default");
@@ -645,11 +645,11 @@ export class RadialMenu implements Layer {
const disabled = this.params === null || item.disabled(this.params);
const color = disabled
? this.config.disabledColor
: item.color || "#333333";
: (item.color ?? "#333333");
const opacity = disabled ? 0.5 : 0.7;
selectedPath.attr(
"fill",
d3.color(color)?.copy({ opacity: opacity })?.toString() || color,
d3.color(color)?.copy({ opacity: opacity })?.toString() ?? color,
);
}
}
@@ -352,9 +352,9 @@ export const buildMenuElement: MenuElement = {
: undefined,
icon: item.icon,
tooltipItems: [
{ text: translateText(item.key || ""), className: "title" },
{ text: translateText(item.key ?? ""), className: "title" },
{
text: translateText(item.description || ""),
text: translateText(item.description ?? ""),
className: "description",
},
{
@@ -401,7 +401,7 @@ export const boatMenuElement: MenuElement = {
params.playerActionHandler.handleBoatAttack(
params.myPlayer,
params.selected?.id() || null,
params.selected?.id() ?? null,
params.tile,
spawn !== false ? spawn : null,
);
+1 -1
View File
@@ -52,7 +52,7 @@ export class TeamStats extends LitElement implements Layer {
for (const player of players) {
const team = player.team();
if (team === null) continue;
if (!grouped[team]) grouped[team] = [];
grouped[team] ??= [];
grouped[team].push(player);
}
+7 -1
View File
@@ -317,10 +317,16 @@ export class UILayer implements Layer {
if (constructionType === undefined) {
return 1;
}
const constDuration =
this.game.unitInfo(constructionType).constructionDuration;
if (constDuration === undefined) {
throw new Error("unit does not have constructionTime");
}
return (
(this.game.ticks() - unit.createdAt()) /
(this.game.unitInfo(constructionType).constructionDuration || 1)
(constDuration === 0 ? 1 : constDuration)
);
case UnitType.MissileSilo:
case UnitType.SAMLauncher:
return unit.missileReadinesss();
+2 -3
View File
@@ -104,9 +104,8 @@ export type IsLoggedInResponse =
| false;
let __isLoggedIn: IsLoggedInResponse | undefined = undefined;
export function isLoggedIn(): IsLoggedInResponse {
if (__isLoggedIn === undefined) {
__isLoggedIn = _isLoggedIn();
}
__isLoggedIn ??= _isLoggedIn();
return __isLoggedIn;
}
function _isLoggedIn(): IsLoggedInResponse {