## Batch D Complete (#1313)

Successfully fixed all low-priority `any` types and catch blocks across 7 files:

### Changes Made:

**1. [lib/types.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/lib/types.ts)**
- Added imports: `NormalizedEntry`, `ExecutionProcessStatus`
- `entry: any` → `entry: NormalizedEntry`
- `process: any` → `process: ExecutionProcess`
- `processStatus: string` → `processStatus: ExecutionProcessStatus`

**2. [lib/modals.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/lib/modals.ts)**
- Removed `any[]` and `component as any`
- Properly typed function arguments with `ShowArgs<P>`
- Used `React.FC<ComponentProps<P>>` for NiceModal compatibility

**3. [EditBranchNameDialog.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/components/dialogs/tasks/EditBranchNameDialog.tsx)**
- `catch (err: any)` → `catch (err: unknown)`
- Used `getErrorMessage(err)` helper

**4. [TagEditDialog.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/components/dialogs/tasks/TagEditDialog.tsx)**
- `catch (err: any)` → `catch (err: unknown)`
- Used `getErrorMessage(err)` helper

**5. [GhCliSetupDialog.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/components/dialogs/auth/GhCliSetupDialog.tsx)**
- `catch (err: any)` → `catch (err: unknown)`
- Added safe type narrowing with `isGhCliSetupError` guard
- Used `getErrorMessage(err)` helper

**6. [ImageUploadSection.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/components/ui/ImageUploadSection.tsx)**
- `catch (error: any)` → `catch (error: unknown)`
- Used `instanceof Error` check

**7. [McpSettings.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/pages/settings/McpSettings.tsx)**
- `catch (err: any)` → `catch (err: unknown)`
- `Record<string, any>` → `Record<string, unknown>` for preconfigured/meta/servers
- Added safe narrowing for meta access

All type checks pass ✓
All formatting complete ✓
This commit is contained in:
Louis Knight-Webb
2025-11-17 22:54:11 +00:00
committed by GitHub
parent 41376eba94
commit b35708e7b9
7 changed files with 60 additions and 29 deletions

View File

@@ -7,7 +7,7 @@ import {
} from '@/components/ui/dialog'; } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import NiceModal, { useModal } from '@ebay/nice-modal-react'; import NiceModal, { useModal } from '@ebay/nice-modal-react';
import { defineModal } from '@/lib/modals'; import { defineModal, getErrorMessage } from '@/lib/modals';
import { attemptsApi } from '@/lib/api'; import { attemptsApi } from '@/lib/api';
import type { GhCliSetupError } from 'shared/types'; import type { GhCliSetupError } from 'shared/types';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
@@ -143,13 +143,25 @@ const GhCliSetupDialogImpl = NiceModal.create<GhCliSetupDialogProps>(
hasResolvedRef.current = true; hasResolvedRef.current = true;
modal.resolve(null); modal.resolve(null);
modal.hide(); modal.hide();
} catch (err: any) { } catch (err: unknown) {
const rawMessage = const rawMessage =
typeof err?.message === 'string' getErrorMessage(err) ||
? err.message t('settings:integrations.github.cliSetup.errors.setupFailed');
: t('settings:integrations.github.cliSetup.errors.setupFailed');
const maybeErrorData =
typeof err === 'object' && err !== null && 'error_data' in err
? (err as { error_data?: unknown }).error_data
: undefined;
const isGhCliSetupError = (x: unknown): x is GhCliSetupError =>
x === 'BREW_MISSING' ||
x === 'SETUP_HELPER_NOT_SUPPORTED' ||
(typeof x === 'object' && x !== null && 'OTHER' in x);
const errorData = isGhCliSetupError(maybeErrorData)
? maybeErrorData
: undefined;
const errorData = err?.error_data as GhCliSetupError | undefined;
const resolvedError: GhCliSetupError = errorData ?? { const resolvedError: GhCliSetupError = errorData ?? {
OTHER: { message: rawMessage }, OTHER: { message: rawMessage },
}; };

View File

@@ -11,7 +11,7 @@ import {
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import NiceModal, { useModal } from '@ebay/nice-modal-react'; import NiceModal, { useModal } from '@ebay/nice-modal-react';
import { defineModal } from '@/lib/modals'; import { defineModal, getErrorMessage } from '@/lib/modals';
import { useRenameBranch } from '@/hooks/useRenameBranch'; import { useRenameBranch } from '@/hooks/useRenameBranch';
export interface EditBranchNameDialogProps { export interface EditBranchNameDialogProps {
@@ -40,8 +40,8 @@ const EditBranchNameDialogImpl = NiceModal.create<EditBranchNameDialogProps>(
} as EditBranchNameDialogResult); } as EditBranchNameDialogResult);
modal.hide(); modal.hide();
}, },
(err: any) => { (err: unknown) => {
setError(err?.message || 'Failed to rename branch'); setError(getErrorMessage(err) || 'Failed to rename branch');
} }
); );

View File

@@ -16,7 +16,7 @@ import { Loader2 } from 'lucide-react';
import { tagsApi } from '@/lib/api'; import { tagsApi } from '@/lib/api';
import type { Tag, CreateTag, UpdateTag } from 'shared/types'; import type { Tag, CreateTag, UpdateTag } from 'shared/types';
import NiceModal, { useModal } from '@ebay/nice-modal-react'; import NiceModal, { useModal } from '@ebay/nice-modal-react';
import { defineModal } from '@/lib/modals'; import { defineModal, getErrorMessage } from '@/lib/modals';
export interface TagEditDialogProps { export interface TagEditDialogProps {
tag?: Tag | null; // null for create mode tag?: Tag | null; // null for create mode
@@ -79,9 +79,10 @@ const TagEditDialogImpl = NiceModal.create<TagEditDialogProps>(({ tag }) => {
modal.resolve('saved' as TagEditResult); modal.resolve('saved' as TagEditResult);
modal.hide(); modal.hide();
} catch (err: any) { } catch (err: unknown) {
setError( setError(
err.message || t('settings.general.tags.dialog.errors.saveFailed') getErrorMessage(err) ||
t('settings.general.tags.dialog.errors.saveFailed')
); );
} finally { } finally {
setSaving(false); setSaving(false);

View File

@@ -151,10 +151,12 @@ export const ImageUploadSection = forwardRef<
} }
setErrorMessage(null); setErrorMessage(null);
} catch (error: any) { } catch (error: unknown) {
console.error('Failed to upload image:', error); console.error('Failed to upload image:', error);
const message = const message =
error.message || 'Failed to upload image. Please try again.'; error instanceof Error
? error.message
: 'Failed to upload image. Please try again.';
setErrorMessage(message); setErrorMessage(message);
} finally { } finally {
setUploadingFiles((prev) => { setUploadingFiles((prev) => {

View File

@@ -23,10 +23,13 @@ export function defineModal<P, R>(
component: React.ComponentType<ComponentProps<P> & NiceModalHocProps> component: React.ComponentType<ComponentProps<P> & NiceModalHocProps>
): Modalized<P, R> { ): Modalized<P, R> {
const c = component as unknown as Modalized<P, R>; const c = component as unknown as Modalized<P, R>;
c.show = ((...args: any[]) => c.show = ((...args: ShowArgs<P>) =>
NiceModal.show(component as any, args[0])) as Modalized<P, R>['show']; NiceModal.show(
c.hide = () => NiceModal.hide(component as any); component as React.FC<ComponentProps<P>>,
c.remove = () => NiceModal.remove(component as any); args[0] as ComponentProps<P>
) as Promise<R>) as Modalized<P, R>['show'];
c.hide = () => NiceModal.hide(component as React.FC<ComponentProps<P>>);
c.remove = () => NiceModal.remove(component as React.FC<ComponentProps<P>>);
return c; return c;
} }

View File

@@ -1,4 +1,8 @@
import { ExecutionProcess } from 'shared/types'; import {
ExecutionProcess,
NormalizedEntry,
ExecutionProcessStatus,
} from 'shared/types';
export type AttemptData = { export type AttemptData = {
processes: ExecutionProcess[]; processes: ExecutionProcess[];
@@ -6,12 +10,12 @@ export type AttemptData = {
}; };
export interface ConversationEntryDisplayType { export interface ConversationEntryDisplayType {
entry: any; entry: NormalizedEntry;
processId: string; processId: string;
processPrompt?: string; processPrompt?: string;
processStatus: string; processStatus: ExecutionProcessStatus;
processIsRunning: boolean; processIsRunning: boolean;
process: any; process: ExecutionProcess;
isFirstInProcess: boolean; isFirstInProcess: boolean;
processIndex: number; processIndex: number;
entryIndex: number; entryIndex: number;

View File

@@ -91,8 +91,11 @@ export function McpSettings() {
const configJson = JSON.stringify(fullConfig, null, 2); const configJson = JSON.stringify(fullConfig, null, 2);
setMcpServers(configJson); setMcpServers(configJson);
setMcpConfigPath(result.config_path); setMcpConfigPath(result.config_path);
} catch (err: any) { } catch (err: unknown) {
if (err?.message && err.message.includes('does not support MCP')) { if (
err instanceof Error &&
err.message.includes('does not support MCP')
) {
setMcpError(err.message); setMcpError(err.message);
} else { } else {
console.error('Error loading MCP servers:', err); console.error('Error loading MCP servers:', err);
@@ -210,14 +213,20 @@ export function McpSettings() {
} }
}; };
const preconfigured = (mcpConfig?.preconfigured ?? {}) as Record<string, any>; const preconfiguredObj = (mcpConfig?.preconfigured ?? {}) as Record<
const meta = (preconfigured.meta ?? {}) as Record< string,
unknown
>;
const meta =
typeof preconfiguredObj.meta === 'object' && preconfiguredObj.meta !== null
? (preconfiguredObj.meta as Record<
string, string,
{ name?: string; description?: string; url?: string; icon?: string } { name?: string; description?: string; url?: string; icon?: string }
>; >)
: {};
const servers = Object.fromEntries( const servers = Object.fromEntries(
Object.entries(preconfigured).filter(([k]) => k !== 'meta') Object.entries(preconfiguredObj).filter(([k]) => k !== 'meta')
) as Record<string, any>; ) as Record<string, unknown>;
const getMetaFor = (key: string) => meta[key] || {}; const getMetaFor = (key: string) => meta[key] || {};
if (!config) { if (!config) {