chore(lint): retire 19 explicit anys, ratchet to 49 warnings (#210)

Event handlers typed as React.MouseEvent, join errors as Error, the
service-worker session setter as strings, the UIA policy map and the
webkitAudioContext probe as narrow shapes. No behaviour change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
2026-09-20 14:13:55 -04:00
co-authored by Claude Opus 5
parent af1c0ee184
commit af244bba75
14 changed files with 24 additions and 19 deletions
+1 -1
View File
@@ -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 68",
"check:eslint": "eslint src/* --max-warnings 49",
"check:prettier": "prettier --check .",
"fix:prettier": "prettier --write .",
"typecheck": "tsc --noEmit",
+1 -1
View File
@@ -30,7 +30,7 @@ export const ImageOverlay = as<'div', ImageOverlayProps>(
<Modal
className={ModalWide}
size="500"
onContextMenu={(evt: any) => evt.stopPropagation()}
onContextMenu={(evt: React.MouseEvent) => evt.stopPropagation()}
>
{renderViewer({
src,
@@ -114,7 +114,7 @@ export function ReadTextFile({ body, mimeType, url, encInfo, renderViewer }: Rea
<Modal
className={ModalWide}
size="500"
onContextMenu={(evt: any) => evt.stopPropagation()}
onContextMenu={(evt: React.MouseEvent) => evt.stopPropagation()}
>
{renderViewer({
name: body,
@@ -203,7 +203,7 @@ export function ReadPdfFile({ body, mimeType, url, encInfo, renderViewer }: Read
<Modal
className={ModalWide}
size="500"
onContextMenu={(evt: any) => evt.stopPropagation()}
onContextMenu={(evt: React.MouseEvent) => evt.stopPropagation()}
>
{renderViewer({
name: body,
@@ -143,7 +143,7 @@ export const ImageContent = as<'div', ImageContentProps>(
<Modal
className={ModalWide}
size="500"
onContextMenu={(evt: any) => evt.stopPropagation()}
onContextMenu={(evt: React.MouseEvent) => evt.stopPropagation()}
>
{renderViewer({
src: srcState.data,
+1 -1
View File
@@ -88,7 +88,7 @@ export function UserHero({ userId, avatarUrl, presence }: UserHeroProps) {
<Modal
size="500"
className={ModalMobileFull}
onContextMenu={(evt: any) => evt.stopPropagation()}
onContextMenu={(evt: React.MouseEvent) => evt.stopPropagation()}
>
<ImageViewer
src={viewAvatar}
+1 -1
View File
@@ -41,7 +41,7 @@ export function CallMemberCard({ member }: CallMemberCardProps) {
className={css.CallMemberCard}
variant="SurfaceVariant"
radii="500"
onClick={(evt: any) =>
onClick={(evt: React.MouseEvent) =>
openUserProfile(
room.roomId,
undefined,
+1 -1
View File
@@ -36,7 +36,7 @@ export function RoomTombstone({ roomId, body, replacementRoomId }: RoomTombstone
<Text size="T400">{body || 'This room has been replaced and is no longer active.'}</Text>
{joinState.status === AsyncStatus.Error && (
<Text style={{ color: color.Critical.Main }} size="T200">
{(joinState.error as any)?.message ?? 'Failed to join replacement room!'}
{(joinState.error as Error | undefined)?.message ?? 'Failed to join replacement room!'}
</Text>
)}
</Box>
+5 -5
View File
@@ -214,7 +214,7 @@ export const MessageAllReactionItem = as<
return (
<>
<Overlay
onContextMenu={(evt: any) => {
onContextMenu={(evt: React.MouseEvent) => {
evt.stopPropagation();
}}
open={open}
@@ -1087,7 +1087,7 @@ export const Message = React.memo(
const handleContextMenu: MouseEventHandler<HTMLDivElement> = (evt) => {
if (evt.altKey || !window.getSelection()?.isCollapsed || edit) return;
const tag = (evt.target as any).tagName;
const tag = (evt.target as HTMLElement | null)?.tagName;
if (typeof tag === 'string' && tag.toLowerCase() === 'a') return;
evt.preventDefault();
if (coarsePointer) {
@@ -1155,7 +1155,7 @@ export const Message = React.memo(
after={<Icon size="100" src={Icons.ReplyArrow} />}
radii="300"
data-event-id={mEvent.getId()}
onClick={(evt: any) => {
onClick={(evt: React.MouseEvent<HTMLButtonElement>) => {
onReplyClick(evt);
closeMenu();
}}
@@ -1232,7 +1232,7 @@ export const Message = React.memo(
after={<Icon src={Icons.ThreadPlus} size="100" />}
radii="300"
data-event-id={mEvent.getId()}
onClick={(evt: any) => {
onClick={(evt: React.MouseEvent<HTMLButtonElement>) => {
onReplyClick(evt, true);
closeMenu();
}}
@@ -1599,7 +1599,7 @@ export const Event = React.memo(
const stateEvent = typeof mEvent.getStateKey() === 'string';
const handleContextMenu: MouseEventHandler<HTMLDivElement> = (evt) => {
if (evt.altKey || !window.getSelection()?.isCollapsed) return;
const tag = (evt.target as any).tagName;
const tag = (evt.target as HTMLElement | null)?.tagName;
if (typeof tag === 'string' && tag.toLowerCase() === 'a') return;
evt.preventDefault();
setMenuAnchor({
+1 -1
View File
@@ -202,7 +202,7 @@ export const Reactions = as<'div', ReactionsProps>(
)}
{reactions.length > 0 && (
<Overlay
onContextMenu={(evt: any) => {
onContextMenu={(evt: React.MouseEvent) => {
evt.stopPropagation();
}}
open={!!viewer}
+1 -1
View File
@@ -378,7 +378,7 @@ export function SpaceTombstone({ roomId, replacementRoomId }: SpaceTombstoneProp
<Text size="T200">This space has been replaced and is no longer active.</Text>
{joinState.status === AsyncStatus.Error && (
<Text className={BreakWord} style={{ color: color.Critical.Main }} size="T200">
{(joinState.error as any)?.message ?? 'Failed to join replacement space!'}
{(joinState.error as Error | undefined)?.message ?? 'Failed to join replacement space!'}
</Text>
)}
</Box>
+1 -1
View File
@@ -368,7 +368,7 @@ export class CallEmbed {
return this.listenEvent('preparing', callback);
}
public onPreparingError(callback: (error: any) => void) {
public onPreparingError(callback: (error: unknown) => void) {
return this.listenEvent('error:preparing', callback);
}
+3 -1
View File
@@ -68,7 +68,9 @@ export const isMLDenoiseSupported = (): boolean => {
// 1. AudioContext/webkitAudioContext (Web Audio API)
// 2. AudioWorklet (Real-time processing in a background thread)
// 3. getUserMedia (Microphone access)
const hasAudioContext = !!(window.AudioContext || (window as any).webkitAudioContext);
const hasAudioContext = !!(
window.AudioContext || (window as Window & { webkitAudioContext?: unknown }).webkitAudioContext
);
// Use `typeof` rather than `!!AudioWorkletNode`: on a browser that has
// AudioContext but no AudioWorkletNode binding (older Safari/Edge), a bare
// reference throws ReferenceError, making this feature-detection helper throw
+4 -1
View File
@@ -72,7 +72,10 @@ export const getLoginTermUrl = (params: UIAParams): string | undefined => {
if (terms.policies === null) return undefined;
if ('privacy_policy' in terms.policies && typeof terms.policies.privacy_policy === 'object') {
if (terms.policies.privacy_policy === null) return undefined;
const langToPolicy = terms.policies.privacy_policy as Record<string, any>;
const langToPolicy = terms.policies.privacy_policy as Record<
string,
{ url?: string } | undefined
>;
const url = langToPolicy.en?.url;
if (typeof url === 'string') return url;
+1 -1
View File
@@ -63,7 +63,7 @@ async function cleanupDeadClients() {
});
}
function setSession(clientId: string, accessToken: any, baseUrl: any) {
function setSession(clientId: string, accessToken: string, baseUrl: string) {
if (typeof accessToken === 'string' && typeof baseUrl === 'string') {
sessions.set(clientId, { accessToken, baseUrl });
} else {