From cfbed15fade5d66ab34155e04f54f98b02155770 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Tue, 10 Jun 2025 00:59:31 -0400 Subject: [PATCH] Avoid using as to cast values (#1115) ## Description: - Use ` is ` return type declarations in favor of `as`. - Use `satisfies` instead of `as`. ## 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 --------- Co-authored-by: Scott Anderson <662325+scottanderson@users.noreply.github.com> --- src/client/graphics/layers/NameLayer.ts | 4 ++-- src/core/execution/utils/BotBehavior.ts | 4 +++- src/core/game/PlayerImpl.ts | 18 ++++++++++-------- tests/MessageTypeClasses.test.ts | 8 ++++---- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/client/graphics/layers/NameLayer.ts b/src/client/graphics/layers/NameLayer.ts index 23f596c01..d322f76f4 100644 --- a/src/client/graphics/layers/NameLayer.ts +++ b/src/client/graphics/layers/NameLayer.ts @@ -12,7 +12,7 @@ import targetIcon from "../../../../resources/images/TargetIcon.svg"; import traitorIcon from "../../../../resources/images/TraitorIcon.svg"; import { PseudoRandom } from "../../../core/PseudoRandom"; import { Theme } from "../../../core/configuration/Config"; -import { AllPlayers, Cell, nukeTypes, UnitType } from "../../../core/game/Game"; +import { AllPlayers, Cell, nukeTypes } from "../../../core/game/Game"; import { GameView, PlayerView } from "../../../core/game/GameView"; import { UserSettings } from "../../../core/game/UserSettings"; import { createCanvas, renderNumber, renderTroops } from "../../Utils"; @@ -516,7 +516,7 @@ export class NameLayer implements Layer { const isSendingNuke = render.player.id() === unit.owner().id(); const notMyPlayer = !myPlayer || unit.owner().id() !== myPlayer.id(); return ( - (nukeTypes as UnitType[]).includes(unit.type()) && + nukeTypes.includes(unit.type()) && isSendingNuke && notMyPlayer && unit.isActive() diff --git a/src/core/execution/utils/BotBehavior.ts b/src/core/execution/utils/BotBehavior.ts index 2cfc95a52..5e393d967 100644 --- a/src/core/execution/utils/BotBehavior.ts +++ b/src/core/execution/utils/BotBehavior.ts @@ -120,7 +120,9 @@ export class BotBehavior { // Prefer neighboring bots const bots = this.player .neighbors() - .filter((n) => n.isPlayer() && n.type() === PlayerType.Bot) as Player[]; + .filter( + (n): n is Player => n.isPlayer() && n.type() === PlayerType.Bot, + ); if (bots.length > 0) { const density = (p: Player) => p.troops() / p.numTilesOwned(); let lowestDensityBot: Player | undefined; diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index 580e38bb6..7a528b284 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -157,7 +157,7 @@ export class PlayerImpl implements Player { troops: a.troops(), id: a.id(), retreating: a.retreating(), - } as AttackUpdate; + } satisfies AttackUpdate; }), incomingAttacks: this._incomingAttacks.map((a) => { return { @@ -166,7 +166,7 @@ export class PlayerImpl implements Player { troops: a.troops(), id: a.id(), retreating: a.retreating(), - } as AttackUpdate; + } satisfies AttackUpdate; }), outgoingAllianceRequests: outgoingAllianceRequests, hasSpawned: this.hasSpawned(), @@ -252,7 +252,9 @@ export class PlayerImpl implements Player { if (this.mg.map().isLand(neighbor)) { const owner = this.mg.map().ownerID(neighbor); if (owner !== this.smallID()) { - ns.add(this.mg.playerBySmallID(owner) as Player | TerraNullius); + ns.add( + this.mg.playerBySmallID(owner) satisfies Player | TerraNullius, + ); } } } @@ -394,7 +396,7 @@ export class PlayerImpl implements Player { if (this.isAlliedWith(recipient)) { throw new Error(`cannot create alliance request, already allies`); } - return this.mg.createAllianceRequest(this, recipient as Player); + return this.mg.createAllianceRequest(this, recipient satisfies Player); } relation(other: Player): Relation { @@ -481,7 +483,7 @@ export class PlayerImpl implements Player { .map((a) => a.other(this)) .flatMap((ally) => ally.targets()); ts.push(...this.targets()); - return [...new Set(ts)] as Player[]; + return [...new Set(ts)] satisfies Player[]; } sendEmoji(recipient: Player | typeof AllPlayers, emoji: string): void { @@ -1007,8 +1009,8 @@ export class PlayerImpl implements Player { if (this.mg.owner(tile) === this) { return false; } - if (this.mg.hasOwner(tile)) { - const other = this.mg.owner(tile) as Player; + const other = this.mg.owner(tile); + if (other.isPlayer()) { if (this.isFriendly(other)) { return false; } @@ -1018,7 +1020,7 @@ export class PlayerImpl implements Player { return false; } if (this.mg.hasOwner(tile)) { - return this.sharesBorderWith(this.mg.owner(tile)); + return this.sharesBorderWith(other); } else { for (const t of this.mg.bfs( tile, diff --git a/tests/MessageTypeClasses.test.ts b/tests/MessageTypeClasses.test.ts index 706600a03..3b7368fc6 100644 --- a/tests/MessageTypeClasses.test.ts +++ b/tests/MessageTypeClasses.test.ts @@ -15,8 +15,8 @@ describe("getMessageTypeClasses", () => { it("should return a valid CSS class for every MessageType", () => { const messageTypes = Object.values(MessageType).filter( - (value) => typeof value === "number", - ) as MessageType[]; + (value): value is MessageType => typeof value === "number", + ); messageTypes.forEach((messageType) => { const result = getMessageTypeClasses(messageType); @@ -30,8 +30,8 @@ describe("getMessageTypeClasses", () => { it("should not trigger console.warn for any MessageType", () => { const messageTypes = Object.values(MessageType).filter( - (value) => typeof value === "number", - ) as MessageType[]; + (value): value is MessageType => typeof value === "number", + ); messageTypes.forEach((messageType) => { getMessageTypeClasses(messageType);