From 42040b6412f618d037aeb7ecc29f96d864904c94 Mon Sep 17 00:00:00 2001 From: Lotus CI Date: Tue, 20 Oct 2026 19:49:15 -0400 Subject: [PATCH] chore(types): fewer any casts; eslint warning ratchet 36 -> 29 (#210) - Developer tools (send event, state event editor, room account data) and setMarkedUnread go through the typed helpers in utils/room and utils/accountData (new setRoomAccountData) instead of casting at the call site; sendStateEvent accepts a developer-chosen type string. - SecretStorage passes the key description as the SDK's SecretStorageKeyDescription, CallEmbed replies with an IWidgetApiRequest, and fillMissingPowers writes through a Record instead of `as any`. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 --- package.json | 2 +- src/app/components/SecretStorage.tsx | 11 +++++++++-- .../common-settings/developer-tools/DevelopTools.tsx | 4 ++-- .../common-settings/developer-tools/SendRoomEvent.tsx | 7 ++++--- .../developer-tools/StateEventEditor.tsx | 3 ++- src/app/hooks/usePowerLevels.ts | 2 +- src/app/plugins/call/CallEmbed.ts | 3 ++- src/app/state/room/markedUnread.ts | 7 +++---- src/app/utils/accountData.ts | 11 +++++++++++ src/app/utils/room.ts | 2 +- 10 files changed, 36 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index cfb5a47d0..cecbbaeec 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "build": "vite build", "preview": "vite preview", "lint": "npm run check:eslint && npm run check:prettier", - "check:eslint": "eslint src/* --max-warnings 36", + "check:eslint": "eslint src/* --max-warnings 29", "check:prettier": "prettier --check .", "fix:prettier": "prettier --write .", "typecheck": "tsc --noEmit", diff --git a/src/app/components/SecretStorage.tsx b/src/app/components/SecretStorage.tsx index 9257a9dd5..c2601ccc3 100644 --- a/src/app/components/SecretStorage.tsx +++ b/src/app/components/SecretStorage.tsx @@ -1,6 +1,7 @@ import React, { FormEventHandler, useCallback } from 'react'; import { Box, Text, Button, Spinner, color } from 'folds'; import { decodeRecoveryKey, deriveRecoveryKeyFromPassphrase } from 'matrix-js-sdk/lib/crypto-api'; +import type { SecretStorageKeyDescription } from 'matrix-js-sdk/lib/secret-storage'; import { PasswordInput } from './password-input'; import { SecretStorageKeyContent, @@ -39,7 +40,10 @@ export function SecretStorageRecoveryPassphrase({ bits, ); - const match = await mx.secretStorage.checkKey(decodedRecoveryKey, keyContent as any); + const match = await mx.secretStorage.checkKey( + decodedRecoveryKey, + keyContent as SecretStorageKeyDescription, + ); if (!match) { throw new Error('Invalid recovery passphrase.'); @@ -132,7 +136,10 @@ export function SecretStorageRecoveryKey({ async (recoveryKey) => { const decodedRecoveryKey = decodeRecoveryKey(recoveryKey); - const match = await mx.secretStorage.checkKey(decodedRecoveryKey, keyContent as any); + const match = await mx.secretStorage.checkKey( + decodedRecoveryKey, + keyContent as SecretStorageKeyDescription, + ); if (!match) { throw new Error('Invalid recovery key.'); diff --git a/src/app/features/common-settings/developer-tools/DevelopTools.tsx b/src/app/features/common-settings/developer-tools/DevelopTools.tsx index 9ff46a9ba..03eee0498 100644 --- a/src/app/features/common-settings/developer-tools/DevelopTools.tsx +++ b/src/app/features/common-settings/developer-tools/DevelopTools.tsx @@ -30,6 +30,7 @@ import { AccountDataSubmitCallback, } from '../../../components/AccountDataEditor'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; +import { setRoomAccountData } from '../../../utils/accountData'; type DeveloperToolsProps = { requestClose: () => void; @@ -58,8 +59,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) { const submitAccountData: AccountDataSubmitCallback = useCallback( async (type, content) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - await mx.setRoomAccountData(room.roomId, type as any, content); + await setRoomAccountData(mx, room.roomId, type, content); }, [mx, room.roomId], ); diff --git a/src/app/features/common-settings/developer-tools/SendRoomEvent.tsx b/src/app/features/common-settings/developer-tools/SendRoomEvent.tsx index 5d8221103..56bbe379a 100644 --- a/src/app/features/common-settings/developer-tools/SendRoomEvent.tsx +++ b/src/app/features/common-settings/developer-tools/SendRoomEvent.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useRef, useState, FormEventHandler, useEffect } from 'react'; -import { MatrixError } from 'matrix-js-sdk'; +import { IContent, MatrixError } from 'matrix-js-sdk'; import { Box, Chip, @@ -22,6 +22,7 @@ import { useTextAreaCodeEditor } from '../../../hooks/useTextAreaCodeEditor'; import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback'; import { syntaxErrorPosition } from '../../../utils/dom'; import { Cursor } from '../../../plugins/text-area'; +import { sendRoomEvent, sendStateEvent } from '../../../utils/room'; const EDITOR_INTENT_SPACE_COUNT = 2; @@ -51,9 +52,9 @@ export function SendRoomEvent({ type, stateKey, requestClose }: SendRoomEventPro useCallback( (evtType, evtStateKey, evtContent) => { if (typeof evtStateKey === 'string') { - return mx.sendStateEvent(room.roomId, evtType as any, evtContent, evtStateKey); + return sendStateEvent(mx, room.roomId, evtType, evtContent, evtStateKey); } - return mx.sendEvent(room.roomId, evtType as any, evtContent); + return sendRoomEvent(mx, room.roomId, null, evtType, evtContent as IContent); }, [mx, room], ), diff --git a/src/app/features/common-settings/developer-tools/StateEventEditor.tsx b/src/app/features/common-settings/developer-tools/StateEventEditor.tsx index 0d89dfd0f..09abd23b5 100644 --- a/src/app/features/common-settings/developer-tools/StateEventEditor.tsx +++ b/src/app/features/common-settings/developer-tools/StateEventEditor.tsx @@ -31,6 +31,7 @@ import { usePowerLevels } from '../../../hooks/usePowerLevels'; import { useTextAreaCodeEditor } from '../../../hooks/useTextAreaCodeEditor'; import { useRoomCreators } from '../../../hooks/useRoomCreators'; import { useRoomPermissions } from '../../../hooks/useRoomPermissions'; +import { sendStateEvent } from '../../../utils/room'; const EDITOR_INTENT_SPACE_COUNT = 2; @@ -59,7 +60,7 @@ function StateEventEdit({ type, stateKey, content, requestClose }: StateEventEdi const [submitState, submit] = useAsyncCallback( useCallback( - (c) => mx.sendStateEvent(room.roomId, type as any, c, stateKey), + (c) => sendStateEvent(mx, room.roomId, type, c, stateKey), [mx, room, type, stateKey], ), ); diff --git a/src/app/hooks/usePowerLevels.ts b/src/app/hooks/usePowerLevels.ts index 7ab9c6402..8ff19cce4 100644 --- a/src/app/hooks/usePowerLevels.ts +++ b/src/app/hooks/usePowerLevels.ts @@ -46,7 +46,7 @@ const fillMissingPowers = (powerLevels: IPowerLevels): IPowerLevels => const keys = Object.keys(DEFAULT_POWER_LEVELS) as unknown as (keyof IPowerLevels)[]; keys.forEach((key) => { if (draftPl[key] === undefined) { - draftPl[key] = DEFAULT_POWER_LEVELS[key] as any; + (draftPl as Record)[key] = DEFAULT_POWER_LEVELS[key]; } }); if (draftPl.notifications && typeof draftPl.notifications.room !== 'number') { diff --git a/src/app/plugins/call/CallEmbed.ts b/src/app/plugins/call/CallEmbed.ts index 2fe594608..0ca525df0 100644 --- a/src/app/plugins/call/CallEmbed.ts +++ b/src/app/plugins/call/CallEmbed.ts @@ -15,6 +15,7 @@ import { WidgetApiFromWidgetAction, WidgetApiToWidgetAction, WidgetDriver, + IWidgetApiRequest, } from 'matrix-widget-api'; import { CallWidgetDriver } from './CallWidgetDriver'; import { trimTrailingSlash } from '../../utils/common'; @@ -796,7 +797,7 @@ export class CallEmbed { const wrapped = (ev: CustomEvent) => { ev.preventDefault(); // Reply with success so the widget transport doesn't time out waiting for a response - this.call.transport.reply(ev.detail as any, {}); + this.call.transport.reply(ev.detail as unknown as IWidgetApiRequest, {}); callback(ev); }; return this.listenEvent(`action:${type}`, wrapped); diff --git a/src/app/state/room/markedUnread.ts b/src/app/state/room/markedUnread.ts index da3a89873..f2f251298 100644 --- a/src/app/state/room/markedUnread.ts +++ b/src/app/state/room/markedUnread.ts @@ -2,6 +2,7 @@ import { atom, useSetAtom } from 'jotai'; import { MatrixClient, MatrixEvent, Room, RoomEvent, RoomEventHandlerMap } from 'matrix-js-sdk'; import { useEffect } from 'react'; import { AccountDataEvent } from '../../../types/matrix/accountData'; +import { setRoomAccountData } from '../../utils/accountData'; // MSC2867 — "mark a room as unread". A per-room account-data flag `{ unread }`. // Stable type `m.marked_unread`; servers/clients predating the stabilization use @@ -25,11 +26,9 @@ export const setMarkedUnread = ( unread: boolean, ): Promise => Promise.all([ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - mx.setRoomAccountData(roomId, AccountDataEvent.MarkedUnread as any, { unread }), + setRoomAccountData(mx, roomId, AccountDataEvent.MarkedUnread, { unread }), // Best-effort mirror for older servers; never fail the primary write on it. - // eslint-disable-next-line @typescript-eslint/no-explicit-any - mx.setRoomAccountData(roomId, UNSTABLE_MARKED_UNREAD as any, { unread }).catch(() => undefined), + setRoomAccountData(mx, roomId, UNSTABLE_MARKED_UNREAD, { unread }).catch(() => undefined), ]); export const receiptIsMine = (event: MatrixEvent, userId: string): boolean => { diff --git a/src/app/utils/accountData.ts b/src/app/utils/accountData.ts index ce0feb310..0248d1124 100644 --- a/src/app/utils/accountData.ts +++ b/src/app/utils/accountData.ts @@ -18,6 +18,17 @@ export function getAccountData( return event?.getContent() as T | undefined; } +/** Room account data under a custom or developer-chosen type (same cast). */ +export function setRoomAccountData( + mx: MatrixClient, + roomId: string, + eventType: string, + content: T, +): Promise { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return (mx as any).setRoomAccountData(roomId, eventType, content); +} + export function setAccountData( mx: MatrixClient, eventType: AccountDataEvent | string, diff --git a/src/app/utils/room.ts b/src/app/utils/room.ts index 68a061dc0..9027348a0 100644 --- a/src/app/utils/room.ts +++ b/src/app/utils/room.ts @@ -60,7 +60,7 @@ export const getStateEvents = (room: Room, eventType: StateEvent): MatrixEvent[] export function sendStateEvent( mx: MatrixClient, roomId: string, - eventType: StateEvent, + eventType: StateEvent | string, content: T, stateKey = '', ): Promise {