From ceedf8ace2241fb28ea7cec26b884f85cd9641ff Mon Sep 17 00:00:00 2001 From: Jack Date: Fri, 13 Sep 2024 15:18:00 +0200 Subject: [PATCH] refactor: enable no-unsafe-call rule (@miodec) (#5883) ### Description ### Checks - [ ] Adding quotes? - [ ] Make sure to include translations for the quotes in the description (or another comment) so we can verify their content. - [ ] Adding a language or a theme? - [ ] If is a language, did you edit `_list.json`, `_groups.json` and add `languages.json`? - [ ] If is a theme, did you add the theme.css? - Also please add a screenshot of the theme, it would be extra awesome if you do so! - [ ] Check if any open issues are related to this PR; if so, be sure to tag them below. - [ ] Make sure the PR title follows the Conventional Commits standard. (https://www.conventionalcommits.org for more info) - [ ] Make sure to include your GitHub username prefixed with @ inside parentheses at the end of the PR title. Closes # --- backend/src/api/controllers/dev.ts | 2 +- backend/src/dal/new-quotes.ts | 4 ++-- backend/src/services/weekly-xp-leaderboard.ts | 6 ++++-- backend/src/utils/daily-leaderboards.ts | 9 ++++++--- backend/src/utils/pb.ts | 20 ++++++++++--------- frontend/src/ts/controllers/ad-controller.ts | 3 +++ .../src/ts/controllers/captcha-controller.ts | 5 +++-- .../src/ts/controllers/eg-ad-controller.ts | 3 +++ .../src/ts/controllers/pw-ad-controller.ts | 1 + .../src/ts/controllers/sound-controller.ts | 6 ++---- frontend/src/ts/elements/test-activity.ts | 4 ++++ frontend/src/ts/pages/settings.ts | 1 + frontend/src/ts/popups/video-ad-popup.ts | 1 + frontend/src/ts/ready.ts | 2 ++ frontend/src/ts/test/british-english.ts | 4 ++-- frontend/src/ts/test/english-punctuation.ts | 2 +- packages/eslint-config/index.js | 2 +- 17 files changed, 48 insertions(+), 27 deletions(-) diff --git a/backend/src/api/controllers/dev.ts b/backend/src/api/controllers/dev.ts index b35e7533f..036a1135d 100644 --- a/backend/src/api/controllers/dev.ts +++ b/backend/src/api/controllers/dev.ts @@ -241,7 +241,7 @@ async function updateUser(uid: string): Promise { timestamp: best.timestamp, } as PersonalBest; - personalBests[mode.mode][mode.mode2].push(entry); + (personalBests[mode.mode][mode.mode2] as PersonalBest[]).push(entry); if (mode.mode === "time") { if (lbPersonalBests[mode.mode][mode.mode2] === undefined) diff --git a/backend/src/dal/new-quotes.ts b/backend/src/dal/new-quotes.ts index 8814cebf6..54e5f1117 100644 --- a/backend/src/dal/new-quotes.ts +++ b/backend/src/dal/new-quotes.ts @@ -1,4 +1,4 @@ -import { simpleGit } from "simple-git"; +import { SimpleGit, simpleGit } from "simple-git"; import { Collection, ObjectId } from "mongodb"; import path from "path"; import { existsSync, writeFileSync } from "fs"; @@ -24,7 +24,7 @@ type QuoteData = { const PATH_TO_REPO = "../../../../monkeytype-new-quotes"; -let git; +let git: SimpleGit | undefined; try { git = simpleGit(path.join(__dirname, PATH_TO_REPO)); } catch (e) { diff --git a/backend/src/services/weekly-xp-leaderboard.ts b/backend/src/services/weekly-xp-leaderboard.ts index 2933d7f4a..df7e6e6ef 100644 --- a/backend/src/services/weekly-xp-leaderboard.ts +++ b/backend/src/services/weekly-xp-leaderboard.ts @@ -96,7 +96,8 @@ export class WeeklyXpLeaderboard { timeTypedSeconds + (currentEntryTimeTypedSeconds ?? 0); const [rank] = await Promise.all([ - // @ts-expect-error + // @ts-expect-error we are doing some weird file to function mapping, thats why its any + // eslint-disable-next-line @typescript-eslint/no-unsafe-call connection.addResultIncrement( 2, weeklyXpLeaderboardScoresKey, @@ -128,7 +129,8 @@ export class WeeklyXpLeaderboard { const { weeklyXpLeaderboardScoresKey, weeklyXpLeaderboardResultsKey } = this.getThisWeeksXpLeaderboardKeys(); - // @ts-expect-error + // @ts-expect-error we are doing some weird file to function mapping, thats why its any + // eslint-disable-next-line @typescript-eslint/no-unsafe-call const [results, scores] = (await connection.getResults( 2, // How many of the arguments are redis keys (https://redis.io/docs/manual/programmability/lua-api/) weeklyXpLeaderboardScoresKey, diff --git a/backend/src/utils/daily-leaderboards.ts b/backend/src/utils/daily-leaderboards.ts index e77bfe401..41b01c263 100644 --- a/backend/src/utils/daily-leaderboards.ts +++ b/backend/src/utils/daily-leaderboards.ts @@ -74,7 +74,8 @@ export class DailyLeaderboard { const resultScore = kogascore(entry.wpm, entry.acc, entry.timestamp); - // @ts-expect-error + // @ts-expect-error we are doing some weird file to function mapping, thats why its any + // eslint-disable-next-line @typescript-eslint/no-unsafe-call const rank = (await connection.addResult( 2, leaderboardScoresKey, @@ -120,7 +121,8 @@ export class DailyLeaderboard { const { leaderboardScoresKey, leaderboardResultsKey } = this.getTodaysLeaderboardKeys(); - // @ts-expect-error + // @ts-expect-error we are doing some weird file to function mapping, thats why its any + // eslint-disable-next-line @typescript-eslint/no-unsafe-call const [results] = (await connection.getResults( 2, leaderboardScoresKey, @@ -213,7 +215,8 @@ export async function purgeUserFromDailyLeaderboards( return; } - // @ts-expect-error + // @ts-expect-error we are doing some weird file to function mapping, thats why its any + // eslint-disable-next-line @typescript-eslint/no-unsafe-call await connection.purgeResults(0, uid, dailyLeaderboardNamespace); } diff --git a/backend/src/utils/pb.ts b/backend/src/utils/pb.ts index 383daa7cb..6011083f4 100644 --- a/backend/src/utils/pb.ts +++ b/backend/src/utils/pb.ts @@ -55,7 +55,7 @@ export function checkAndUpdatePb( const didUpdate = updatePersonalBest(personalBestMatch, result); isPb = didUpdate; } else { - userPb[mode][mode2].push(buildPersonalBest(result)); + (userPb[mode][mode2] as PersonalBest[]).push(buildPersonalBest(result)); } if (!_.isNil(lbPersonalBests)) { @@ -186,15 +186,17 @@ export function updateLeaderboardPersonalBests( lbPb[mode] ??= {}; lbPb[mode][mode2] ??= {}; const bestForEveryLanguage = {}; - userPersonalBests[mode][mode2].forEach((pb: PersonalBest) => { - const language = pb.language; - if ( - bestForEveryLanguage[language] === undefined || - bestForEveryLanguage[language].wpm < pb.wpm - ) { - bestForEveryLanguage[language] = pb; + (userPersonalBests[mode][mode2] as PersonalBest[]).forEach( + (pb: PersonalBest) => { + const language = pb.language; + if ( + bestForEveryLanguage[language] === undefined || + bestForEveryLanguage[language].wpm < pb.wpm + ) { + bestForEveryLanguage[language] = pb; + } } - }); + ); _.each(bestForEveryLanguage, (pb: PersonalBest, language: string) => { const languageDoesNotExist = lbPb[mode][mode2][language] === undefined; const languageIsEmpty = _.isEmpty(lbPb[mode][mode2][language]); diff --git a/frontend/src/ts/controllers/ad-controller.ts b/frontend/src/ts/controllers/ad-controller.ts index d6d23b7c1..e68db230a 100644 --- a/frontend/src/ts/controllers/ad-controller.ts +++ b/frontend/src/ts/controllers/ad-controller.ts @@ -175,6 +175,7 @@ export async function checkCookieblocker(): Promise { return; } //@ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unsafe-call window.__tcfapi("getTCData", 2, (tcData, success) => { if (success as boolean) { if (tcData.eventStatus === "cmpuishown") { @@ -268,11 +269,13 @@ export function updateFooterAndVerticalAds(visible: boolean): void { export function showConsentPopup(): void { if (choice === "eg") { //@ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unsafe-call window.__tcfapi("displayConsentUi", 2, function () { // }); } else { //@ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unsafe-call ramp.showCmpModal(); } } diff --git a/frontend/src/ts/controllers/captcha-controller.ts b/frontend/src/ts/controllers/captcha-controller.ts index 46aee7b37..68bb1b972 100644 --- a/frontend/src/ts/controllers/captcha-controller.ts +++ b/frontend/src/ts/controllers/captcha-controller.ts @@ -13,7 +13,7 @@ export function render( } //@ts-expect-error - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call const widgetId = grecaptcha.render(element, { sitekey: siteKey, callback, @@ -28,6 +28,7 @@ export function reset(id: string): void { } //@ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unsafe-call grecaptcha.reset(captchas[id]); } @@ -37,6 +38,6 @@ export function getResponse(id: string): string { } //@ts-expect-error - // eslint-disable-next-line @typescript-eslint/no-unsafe-return + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call return grecaptcha.getResponse(captchas[id]); } diff --git a/frontend/src/ts/controllers/eg-ad-controller.ts b/frontend/src/ts/controllers/eg-ad-controller.ts index 12fb71709..ff09ed60d 100644 --- a/frontend/src/ts/controllers/eg-ad-controller.ts +++ b/frontend/src/ts/controllers/eg-ad-controller.ts @@ -15,6 +15,7 @@ export function init(): void { export function renderResult(widerThanBreakpoint: boolean): void { if (widerThanBreakpoint) { //@ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unsafe-call window.egAps.render([ "ad-result", "ad-vertical-left", @@ -23,6 +24,7 @@ export function renderResult(widerThanBreakpoint: boolean): void { ]); } else { //@ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unsafe-call window.egAps.render([ "ad-result-small", "ad-vertical-left", @@ -35,6 +37,7 @@ export function renderResult(widerThanBreakpoint: boolean): void { export function reinstate(): boolean { try { //@ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unsafe-call window.egAps.reinstate(); return true; } catch (e) { diff --git a/frontend/src/ts/controllers/pw-ad-controller.ts b/frontend/src/ts/controllers/pw-ad-controller.ts index dd5378838..d30b17cfd 100644 --- a/frontend/src/ts/controllers/pw-ad-controller.ts +++ b/frontend/src/ts/controllers/pw-ad-controller.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unsafe-call */ //@ts-nocheck import Config from "../config"; diff --git a/frontend/src/ts/controllers/sound-controller.ts b/frontend/src/ts/controllers/sound-controller.ts index 2455a0570..61a16e48b 100644 --- a/frontend/src/ts/controllers/sound-controller.ts +++ b/frontend/src/ts/controllers/sound-controller.ts @@ -412,10 +412,8 @@ export async function previewError(val: string): Promise { const errorSoundIds = Object.keys(safeErrorSounds); if (!errorSoundIds.includes(val)) return; - //@ts-expect-error - errorClickSounds[val][0].sounds[0].seek(0); - //@ts-expect-error - errorClickSounds[val][0].sounds[0].play(); + errorSounds?.[val]?.[0]?.sounds[0]?.seek(0); + errorSounds?.[val]?.[0]?.sounds[0]?.play(); } let currentCode = "KeyA"; diff --git a/frontend/src/ts/elements/test-activity.ts b/frontend/src/ts/elements/test-activity.ts index 069027bad..51e328c7f 100644 --- a/frontend/src/ts/elements/test-activity.ts +++ b/frontend/src/ts/elements/test-activity.ts @@ -85,6 +85,7 @@ export function initYearSelector( const yearSelect = getYearSelector(); // eslint-disable-next-line @typescript-eslint/no-unsafe-argument yearSelect.setData(years); + // eslint-disable-next-line @typescript-eslint/no-unsafe-call years.length > 1 ? yearSelect.enable() : yearSelect.disable(); } @@ -108,11 +109,14 @@ function getYearSelector(): SlimSelect { }, events: { afterChange: async (newVal): Promise => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call yearSelector?.disable(); const selected = newVal[0]?.value as string; const activity = await getTestActivityCalendar(selected); update(activity); + // eslint-disable-next-line @typescript-eslint/no-unsafe-call if ((yearSelector?.getData() ?? []).length > 1) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call yearSelector?.enable(); } }, diff --git a/frontend/src/ts/pages/settings.ts b/frontend/src/ts/pages/settings.ts index 0c28aef76..9861f68ae 100644 --- a/frontend/src/ts/pages/settings.ts +++ b/frontend/src/ts/pages/settings.ts @@ -426,6 +426,7 @@ function reset(): void { $(".pageSettings .section[data-config-name='fontFamily'] .buttons").empty(); for (const select of document.querySelectorAll(".pageSettings select")) { //@ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unsafe-call select?.slim?.destroy?.(); } } diff --git a/frontend/src/ts/popups/video-ad-popup.ts b/frontend/src/ts/popups/video-ad-popup.ts index dbf39e64d..c8b4382e1 100644 --- a/frontend/src/ts/popups/video-ad-popup.ts +++ b/frontend/src/ts/popups/video-ad-popup.ts @@ -38,6 +38,7 @@ export async function show(): Promise { .removeClass("hidden") .animate({ opacity: 1 }, 125, () => { //@ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unsafe-call window.dataLayer.push({ event: "EG_Video" }); }); } diff --git a/frontend/src/ts/ready.ts b/frontend/src/ts/ready.ts index 1fea438cc..03c681500 100644 --- a/frontend/src/ts/ready.ts +++ b/frontend/src/ts/ready.ts @@ -43,6 +43,8 @@ $((): void => { } MonkeyPower.init(); + // untyped, need to ignore + // eslint-disable-next-line @typescript-eslint/no-unsafe-call new Konami("https://keymash.io/"); if (Misc.isDevEnvironment()) { diff --git a/frontend/src/ts/test/british-english.ts b/frontend/src/ts/test/british-english.ts index 365dc5096..ae4335157 100644 --- a/frontend/src/ts/test/british-english.ts +++ b/frontend/src/ts/test/british-english.ts @@ -46,8 +46,8 @@ export async function replace( RegExp(`^(?:([\\W]*)(${replacement[0]})([\\W]*))$`, "gi"), (_, $1, $2, $3) => $1 + - ($2.charAt(0) === $2.charAt(0).toUpperCase() - ? $2 === $2.toUpperCase() + (($2 as string).charAt(0) === ($2 as string).charAt(0).toUpperCase() + ? $2 === ($2 as string).toUpperCase() ? replacement[1].toUpperCase() : capitalizeFirstLetterOfEachWord(replacement[1]) : replacement[1]) + diff --git a/frontend/src/ts/test/english-punctuation.ts b/frontend/src/ts/test/english-punctuation.ts index 513f4be4d..808e7bdae 100644 --- a/frontend/src/ts/test/english-punctuation.ts +++ b/frontend/src/ts/test/english-punctuation.ts @@ -57,7 +57,7 @@ export async function replace(word: string): Promise { RegExp(`^(?:([\\W]*)(${replacement[0]})([\\W]*))$`, "gi"), (_, $1, $2, $3) => $1 + - ($2.charAt(0) === $2.charAt(0).toUpperCase() + (($2 as string).charAt(0) === ($2 as string).charAt(0).toUpperCase() ? shouldWholeReplacementWordBeCapitalised($2 as string) ? randomReplacement.toUpperCase() : capitalizeFirstLetterOfEachWord(randomReplacement) diff --git a/packages/eslint-config/index.js b/packages/eslint-config/index.js index f49363209..d386b238e 100644 --- a/packages/eslint-config/index.js +++ b/packages/eslint-config/index.js @@ -80,10 +80,10 @@ module.exports = { "@typescript-eslint/restrict-plus-operands": "off", // TODO: enable at some point - "@typescript-eslint/no-unsafe-call": "off", //~76 "@typescript-eslint/no-unsafe-member-access": "off", //~105 // + "@typescript-eslint/no-unsafe-call": "error", "@typescript-eslint/no-unsafe-argument": "error", "@typescript-eslint/no-unsafe-assignment": "error", "@typescript-eslint/no-unnecessary-type-assertion": "error",