Enable a few more lint rules

This commit is contained in:
Guangcong Luo 2025-02-22 01:29:17 -08:00
parent 7c21d0f504
commit ad5f389db5
11 changed files with 31 additions and 44 deletions

View File

@ -57,14 +57,8 @@ export const defaultRules = {
"@stylistic/new-parens": "off", // used for the `new class {...}` pattern
"no-prototype-builtins": "off",
// typescript-eslint defaults too strict
// =====================================
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-unsafe-argument": "off",
// defaults too strict
// ===================
"no-empty": ["error", {"allowEmptyCatch": true}],
"no-case-declarations": "off",
@ -180,15 +174,12 @@ export const defaultRulesTS = {
// TODO: revisit
// we should do this someday but it'd have to be a gradual manual process
"@typescript-eslint/explicit-module-boundary-types": "off",
// "@typescript-eslint/explicit-module-boundary-types": "off",
// like above but slightly harder, so do that one first
"@typescript-eslint/explicit-function-return-type": "off",
// "@typescript-eslint/explicit-function-return-type": "off",
// probably we should settle on a standard someday
"@typescript-eslint/member-ordering": "off",
// "@typescript-eslint/member-ordering": "off",
// "@typescript-eslint/no-extraneous-class": "error",
// "@typescript-eslint/no-type-alias": "error",
"@typescript-eslint/prefer-optional-chain": "off",
"@typescript-eslint/consistent-type-imports": "error", // TODO after no-duplicate-imports fix
// maybe we should consider this
"@typescript-eslint/consistent-indexed-object-style": "off",
@ -203,10 +194,11 @@ export const defaultRulesTS = {
"no-unused-expressions": "off",
"@typescript-eslint/no-unused-expressions": defaultRules["no-unused-expressions"],
// PS code (code specific to PS)
// =============================
"@typescript-eslint/unbound-method": "off", // used for sim event handlers, command handlers, etc
"@typescript-eslint/no-require-imports": "off",
// defaults too strict
// ===================
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
// probably bugs
// =============
@ -214,6 +206,7 @@ export const defaultRulesTS = {
"@typescript-eslint/no-extra-non-null-assertion": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
"@typescript-eslint/consistent-type-imports": "error",
// naming style
// ============
@ -245,10 +238,6 @@ export const defaultRulesTS = {
/** @type {NonNullable<Config['rules']>} */
export const defaultRulesTSChecked = {
...defaultRulesTS,
// yes-types
// =========
// "@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/prefer-includes": "error",
// we use `any`
// ============
@ -256,9 +245,11 @@ export const defaultRulesTSChecked = {
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-unsafe-argument": "off",
// yes-types syntax style, overriding base
// =======================================
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-nullish-coalescing": "off",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/no-confusing-non-null-assertion": "off",

View File

@ -742,7 +742,7 @@ abstract class BattleTypedSearch<T extends SearchType> {
if (this.sortRow) {
results = [this.sortRow, ...results];
}
if (illegalResults && illegalResults.length) {
if (illegalResults?.length) {
results = [...results, ['header', "Illegal results"], ...illegalResults];
}
return results;
@ -856,7 +856,7 @@ abstract class BattleTypedSearch<T extends SearchType> {
this.formatType === 'natdex' ? `gen${gen}natdex` :
this.formatType === 'stadium' ? `gen${gen}stadium${gen > 1 ? gen : ''}` :
`gen${gen}`;
if (table && table[tableKey]) {
if (table?.[tableKey]) {
table = table[tableKey];
}
if (!table) return pokemon.tier;

View File

@ -502,7 +502,7 @@ export const Dex = new class implements ModdedDex {
if (!type || typeof type === 'string') {
const id = toID(type) as string;
const name = id.substr(0, 1).toUpperCase() + id.substr(1);
type = (window.BattleTypeChart && window.BattleTypeChart[id]) || {};
type = window.BattleTypeChart?.[id] || {};
if (type.damageTaken) type.exists = true;
if (!type.id) type.id = id;
if (!type.name) type.name = name;
@ -524,7 +524,7 @@ export const Dex = new class implements ModdedDex {
isName: (name: string | null): boolean => {
const id = toID(name);
if (name !== id.substr(0, 1).toUpperCase() + id.substr(1)) return false;
return (window.BattleTypeChart || {}).hasOwnProperty(id);
return window.BattleTypeChart?.hasOwnProperty(id);
},
};

View File

@ -267,8 +267,7 @@ export class PSSearchResults extends preact.Component<{search: DexSearch}> {
renderArticleRow(id: ID, matchStart: number, matchEnd: number, errorMessage?: preact.ComponentChildren) {
const isSearchType = (id === 'pokemon' || id === 'moves');
const name = (window.BattleArticleTitles && window.BattleArticleTitles[id]) ||
(id.charAt(0).toUpperCase() + id.substr(1));
const name = window.BattleArticleTitles?.[id] || (id.charAt(0).toUpperCase() + id.substr(1));
return <li class="result"><a href={`${this.URL_ROOT}articles/${id}`} data-target="push" data-entry={`article|${name}`}>
<span class="col namecol">{this.renderName(name, matchStart, matchEnd)}</span>
@ -387,13 +386,11 @@ export class PSSearchResults extends preact.Component<{search: DexSearch}> {
)}
{!search.query && <small style="color: #888">(backspace = delete filter)</small>}
</p>}
{search.results && (
{
// TODO: implement windowing
// for now, just show first twenty results
search.results.slice(0, 20).map(result =>
this.renderRow(result)
)
)}
search.results?.slice(0, 20).map(result => this.renderRow(result))
}
</ul>;
}
}

View File

@ -380,7 +380,7 @@ export class BattleTextParser {
static stat(stat: string) {
const entry = BattleText[stat || "stats"];
if (!entry || !entry.statName) return `???stat:${stat}???`;
if (!entry?.statName) return `???stat:${stat}???`;
return entry.statName;
}

View File

@ -3088,11 +3088,11 @@ class BattleStatGuesser {
let baseStat = species.baseStats[stat];
let iv = (set.ivs && set.ivs[stat]);
let iv = set.ivs?.[stat];
if (typeof iv !== 'number') iv = 31;
if (this.dex.gen <= 2) iv &= 30;
let ev = (set.evs && set.evs[stat]);
let ev = set.evs?.[stat];
if (typeof ev !== 'number') ev = (this.dex.gen > 2 ? 0 : 252);
if (evOverride !== undefined) ev = evOverride;

View File

@ -216,7 +216,7 @@ export class Pokemon implements PokemonDetails, PokemonHealth {
healthParse(hpstring: string, parsedamage?: boolean, heal?: boolean):
[number, number, number] | [number, number, number, number, HPColor] | null {
// returns [delta, denominator, percent(, oldnum, oldcolor)] or null
if (!hpstring || !hpstring.length) return null;
if (!hpstring?.length) return null;
let parenIndex = hpstring.lastIndexOf('(');
if (parenIndex >= 0) {
// old style damage and health reporting

View File

@ -461,7 +461,7 @@ class TeamDropdown extends preact.Component<{format: string}> {
render() {
const teamFormat = PS.teams.teambuilderFormat(this.props.format);
const formatData = window.BattleFormats?.[teamFormat];
if (formatData && formatData.team) {
if (formatData?.team) {
return <button class="select teamselect preselected" name="team" value="random" disabled>
<div class="team">
<strong>Random team</strong>

View File

@ -166,7 +166,7 @@ class RoomsPanel extends PSRoomPanel {
</div></PSPanelWrapper>;
}
renderRoomList(title: string, rooms?: RoomInfo[]) {
if (!rooms || !rooms.length) return null;
if (!rooms?.length) return null;
// Descending order
const sortedRooms = rooms.sort((a, b) => (b.userCount || 0) - (a.userCount || 0));
return <div class="roomlist">

View File

@ -327,7 +327,7 @@ export class PSMain extends preact.Component {
PS.prefs.subscribeAndRun(key => {
if (!key || key === 'theme') {
const dark = PS.prefs.theme === 'dark' ||
(PS.prefs.theme === 'system' && colorSchemeQuery && colorSchemeQuery.matches);
(PS.prefs.theme === 'system' && colorSchemeQuery?.matches);
document.body.className = dark ? 'dark' : '';
}
});

View File

@ -10,7 +10,7 @@ import type {ID} from '../../play.pokemonshowdown.com/src/battle-dex';
declare function toID(input: string): string;
function showAd(id: string) {
// @ts-expect-error
// @ts-expect-error no clue how to declare this one
window.top.__vm_add = window.top.__vm_add || [];
// this is a x-browser way to make sure content has loaded.
@ -34,7 +34,7 @@ function showAd(id: string) {
placement.setAttribute("data-id", "645268557bc7b571c2f06f62");
}
document.querySelector("#" + id)!.appendChild(placement);
// @ts-expect-error
// @ts-expect-error no clue how to declare this one
window.top.__vm_add.push(placement);
});
}
@ -160,14 +160,13 @@ export class BattlePanel extends preact.Component<{id: string}> {
}
}
keyPressed = (e: KeyboardEvent) => {
// @ts-ignore
this.lastUsedKeyCode = `${e.keyCode}`;
if (e.ctrlKey || e.metaKey || e.altKey) return;
if (e.keyCode === 27 && this.turnView) { // Esc
this.closeTurn();
return;
}
// @ts-ignore
// @ts-expect-error really wish they let me assert that the target is an HTMLElement
if (e.target?.tagName === 'INPUT' || e.target?.tagName === 'SELECT') return;
switch (e.keyCode) {
case 75: // k