chore(lint): no-explicit-any in small app files (batch 1)

This commit is contained in:
Mohamed Boudra
2026-04-24 06:35:38 +07:00
parent 537a2a2929
commit 056dc46e74
22 changed files with 49 additions and 29 deletions

View File

@@ -680,7 +680,7 @@ function OfferLinkListener({
void upsertDaemonFromOfferUrl(url)
.then((profile) => {
if (cancelled) return;
const serverId = (profile as any)?.serverId;
const serverId = (profile as { serverId?: unknown } | null)?.serverId;
if (typeof serverId !== "string" || !serverId) return;
router.replace(buildHostRootRoute(serverId));
return;

View File

@@ -1,6 +1,6 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Alert, Pressable, Text, View } from "react-native";
import { useLocalSearchParams, useRouter } from "expo-router";
import { useLocalSearchParams, useRouter, type Href } from "expo-router";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
import { CameraView, useCameraPermissions } from "expo-camera";
@@ -147,7 +147,7 @@ export default function PairScanScreen() {
try {
router.back();
} catch {
router.replace("/" as any);
router.replace("/" as Href);
}
}, [router]);

View File

@@ -1,5 +1,5 @@
import { forwardRef, useCallback, useEffect, useMemo } from "react";
import type { ReactNode } from "react";
import type { ReactNode, Ref } from "react";
import { createPortal } from "react-dom";
import { Modal, Pressable, ScrollView, Text, TextInput, View } from "react-native";
import type { TextInputProps } from "react-native";
@@ -333,7 +333,7 @@ export const AdaptiveTextInput = forwardRef<TextInput, TextInputProps>(
const isMobile = useIsCompactFormFactor();
if (isMobile) {
return <BottomSheetTextInput ref={ref as any} {...props} />;
return <BottomSheetTextInput ref={ref as unknown as Ref<never>} {...props} />;
}
return <TextInput ref={ref} {...props} />;

View File

@@ -10,7 +10,7 @@ import {
} from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useCallback, useMemo, useState, type ReactElement } from "react";
import { router } from "expo-router";
import { router, type Href } from "expo-router";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
import { useIsCompactFormFactor } from "@/constants/layout";
import { formatTimeAgo } from "@/utils/time";
@@ -319,7 +319,7 @@ export function AgentList({
onAgentSelect?.();
if (!workspaceId) {
router.navigate(buildHostAgentDetailRoute(serverId, agentId) as any);
router.navigate(buildHostAgentDetailRoute(serverId, agentId) as Href);
return;
}

View File

@@ -1,3 +1,5 @@
import type { Theme } from "@/styles/theme";
/**
* Compute the pixel width for a line-number gutter based on the highest
* line number that will be displayed. Minimum width accommodates 2 digits.
@@ -7,7 +9,7 @@ export function lineNumberGutterWidth(maxLineNumber: number): number {
return digits * 8 + 12;
}
export function getCodeInsets(theme: any) {
export function getCodeInsets(theme: Theme) {
let padding: number;
if (typeof theme.spacing?.[3] === "number") padding = theme.spacing[3];
else if (typeof theme.spacing?.[4] === "number") padding = theme.spacing[4];

View File

@@ -1,4 +1,5 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import type { Ref } from "react";
import {
View,
Text,
@@ -462,7 +463,7 @@ function ProviderSearchInput({
<View style={styles.providerSearchContainer}>
<Search size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
<InputComponent
ref={inputRef as any}
ref={inputRef as unknown as Ref<never>}
// @ts-expect-error - outlineStyle is web-only
style={inputStyle}
placeholder="Search models..."

View File

@@ -389,7 +389,7 @@ const styles = StyleSheet.create((theme) => ({
fontSize: theme.fontSize.lg,
paddingVertical: theme.spacing[1],
outlineStyle: "none",
} as any,
} as object,
results: {
flexGrow: 0,
},

View File

@@ -6,7 +6,11 @@ import {
type StyleProp,
type ViewStyle,
} from "react-native";
import { ScrollView, type ScrollView as ScrollViewType } from "react-native-gesture-handler";
import {
ScrollView,
type ScrollView as ScrollViewType,
type GestureType,
} from "react-native-gesture-handler";
import { useHorizontalScrollOptional } from "@/contexts/horizontal-scroll-context";
import { useExplorerSidebarAnimation } from "@/contexts/explorer-sidebar-animation-context";
@@ -31,7 +35,7 @@ export function DiffScroll({
const scrollViewRef = useRef<ScrollViewType>(null);
// Get the close gesture ref from animation context (may not be available outside sidebar)
let closeGestureRef: React.MutableRefObject<any> | undefined;
let closeGestureRef: React.MutableRefObject<GestureType | undefined> | undefined;
try {
const animation = useExplorerSidebarAnimation();
closeGestureRef = animation.closeGestureRef;

View File

@@ -590,4 +590,4 @@ const styles = StyleSheet.create((theme) => ({
}));
const DESKTOP_SIDEBAR_BORDER_STYLE = [styles.desktopSidebarBorder, { flex: 1 }];
const RESIZE_HANDLE_STYLE = [styles.resizeHandle, isWeb && ({ cursor: "col-resize" } as any)];
const RESIZE_HANDLE_STYLE = [styles.resizeHandle, isWeb && ({ cursor: "col-resize" } as object)];

View File

@@ -39,7 +39,7 @@ export function HeaderToggleButton({
const expandedState = (props.accessibilityState as { expanded?: boolean } | undefined)?.expanded;
const ariaExpandedProps =
isWeb && typeof expandedState === "boolean"
? ({ "aria-expanded": expandedState } as any)
? ({ "aria-expanded": expandedState } as Record<string, boolean>)
: null;
const combinedStyle = useMemo(() => [headerIconSlotStyle.slot, style], [style]);

View File

@@ -728,7 +728,7 @@ function DesktopSidebar({
);
const desktopSidebarBorderStyle = useMemo(() => [styles.desktopSidebarBorder, { flex: 1 }], []);
const resizeHandleStyle = useMemo(
() => [styles.resizeHandle, isWeb && ({ cursor: "col-resize" } as any)],
() => [styles.resizeHandle, isWeb && ({ cursor: "col-resize" } as object)],
[],
);

View File

@@ -300,7 +300,7 @@ const styles = StyleSheet.create((theme) => ({
fontSize: theme.fontSize.lg,
paddingVertical: theme.spacing[1],
outlineStyle: "none",
} as any,
} as object,
results: {
flexGrow: 0,
},

View File

@@ -1,4 +1,4 @@
import { useMemo } from "react";
import { useMemo, type Ref } from "react";
import { useDroppable } from "@dnd-kit/core";
import { View } from "react-native";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
@@ -62,7 +62,7 @@ export function SplitDropZone({ paneId, active, preview }: SplitDropZoneProps) {
}
return (
<View ref={setNodeRef as any} style={styles.overlay} pointerEvents="none">
<View ref={setNodeRef as unknown as Ref<View>} style={styles.overlay} pointerEvents="none">
{previewStyles ? (
<>
<View pointerEvents="none" style={previewStyles.overlay} />

View File

@@ -1,5 +1,5 @@
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
import type { ReactElement, ReactNode } from "react";
import type { ReactElement, ReactNode, Ref } from "react";
import {
View,
Text,
@@ -155,7 +155,7 @@ export function SearchInput({
<View style={styles.searchInputContainer}>
<Search size={16} color={theme.colors.foregroundMuted} />
<InputComponent
ref={inputRef as any}
ref={inputRef as unknown as Ref<never>}
// @ts-expect-error - outlineStyle is web-only
style={SEARCH_INPUT_STYLE}
placeholder={placeholder}

View File

@@ -196,5 +196,5 @@ const styles = StyleSheet.create((theme) => ({
paddingVertical: theme.spacing[2],
paddingHorizontal: theme.spacing[3],
outlineStyle: "none",
} as any,
} as object,
}));

View File

@@ -209,7 +209,7 @@ export function useCommandCenter() {
workspaceDirectory: agent.cwd,
});
if (!workspaceId) {
router.navigate(buildHostAgentDetailRoute(agent.serverId, agent.id) as any);
router.navigate(buildHostAgentDetailRoute(agent.serverId, agent.id) as Href);
return;
}
const route = prepareWorkspaceTab({

View File

@@ -1,5 +1,5 @@
import { useCallback } from "react";
import { router } from "expo-router";
import { router, type Href } from "expo-router";
import type { DaemonClient } from "@server/client/daemon-client";
import { useHostRuntimeClient, useHostRuntimeIsConnected } from "@/runtime/host-runtime";
import {
@@ -76,7 +76,7 @@ export function useOpenProject(serverId: string | null): (path: string) => Promi
draftId: generateDraftId(),
}),
replaceRoute: (route) => {
router.replace(route as any);
router.replace(route as Href);
},
});
},

View File

@@ -75,7 +75,7 @@ declare global {
const isMac =
typeof navigator !== "undefined" &&
(/Macintosh|Mac OS/i.test(navigator.userAgent ?? "") ||
/Mac/i.test((navigator as any).platform ?? ""));
/Mac/i.test((navigator as Navigator & { platform?: string }).platform ?? ""));
const DEFAULT_TOUCH_SCROLL_LINE_HEIGHT_PX = 18;
const FIT_TIMEOUT_DELAYS_MS = [0, 16, 48, 120, 250, 500, 1_000, 2_000];

View File

@@ -25,7 +25,9 @@ export function resolveAppVersion(): string | null {
return expoVersion;
}
const manifestVersion = toVersionOrNull((Constants as any).manifest?.version);
const manifestVersion = toVersionOrNull(
(Constants as unknown as { manifest?: { version?: unknown } }).manifest?.version,
);
if (manifestVersion) {
return manifestVersion;
}

View File

@@ -51,7 +51,18 @@ function getWebNotificationConstructor(): {
},
): unknown;
} | null {
const NotificationConstructor = (globalThis as { Notification?: any }).Notification;
const NotificationConstructor = (
globalThis as {
Notification?: {
permission: string;
requestPermission?: () => Promise<string>;
new (
title: string,
options?: { body?: string; data?: Record<string, unknown>; icon?: string },
): unknown;
};
}
).Notification;
return NotificationConstructor ?? null;
}

View File

@@ -10,7 +10,7 @@ export function getShortcutOs(): ShortcutOs {
if (getIsElectronRuntimeMac()) return "mac";
if (typeof navigator === "undefined") return "non-mac";
const ua = navigator.userAgent ?? "";
const platform = (navigator as any).platform ?? "";
const platform = (navigator as Navigator & { platform?: string }).platform ?? "";
const isApple =
/Macintosh|Mac OS|iPhone|iPad|iPod/i.test(ua) || /Mac|iPhone|iPad|iPod/i.test(platform);
return isApple ? "mac" : "non-mac";

View File

@@ -1,7 +1,7 @@
// @ts-nocheck
import { vi } from "vitest";
const globalWithTestShims = globalThis as typeof globalThis & Record<string, any>;
const globalWithTestShims = globalThis as typeof globalThis & Record<string, unknown>;
globalWithTestShims.__DEV__ = false;