mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-24 08:44:06 +00:00
Road to No Explicit Any Part 11 (#8565)
## Summary
This PR removes `any` types from widgets, services, stores, and test
files, replacing them with proper TypeScript types.
### Key Changes
#### Type Safety Improvements
- Replaced `any` with `unknown`, explicit types, or proper interfaces
across widgets and services
- Added proper type imports (TgpuRoot, Point, StyleValue, etc.)
- Created typed interfaces (NumericWidgetOptions, TestWindow,
ImportFailureDetail, etc.)
- Fixed function return types to be non-nullable where appropriate
- Added type guards and null checks instead of non-null assertions
- Used `ComponentProps` from vue-component-type-helpers for component
testing
#### Widget System
- Added index signature to IWidgetOptions for Record compatibility
- Centralized disabled logic in WidgetInputNumberInput
- Moved template type assertions to computed properties
- Fixed ComboWidget getOptionLabel type assertions
- Improved remote widget type handling with runtime checks
#### Services & Stores
- Fixed getOrCreateViewer to return non-nullable values
- Updated addNodeOnGraph to use specific options type `{ pos?: Point }`
- Added proper type assertions for settings store retrieval
- Fixed executionIdToCurrentId return type (string | undefined)
#### Test Infrastructure
- Exported GraphOrSubgraph from litegraph barrel to avoid circular
dependencies
- Updated test fixtures with proper TypeScript types (TestInfo,
LGraphNode)
- Replaced loose Record types with ComponentProps in tests
- Added proper error handling in WebSocket fixture
#### Code Organization
- Created shared i18n-types module for locale data types
- Made ImportFailureDetail non-exported (internal use only)
- Added @public JSDoc tag to ElectronWindow type
- Fixed console.log usage in scripts to use allowed methods
### Files Changed
**Widgets & Components:**
-
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
-
src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue
-
src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue
- src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.vue
-
src/renderer/extensions/vueNodes/widgets/composables/useRemoteWidget.ts
- src/lib/litegraph/src/widgets/ComboWidget.ts
- src/lib/litegraph/src/types/widgets.ts
- src/components/common/LazyImage.vue
- src/components/load3d/Load3dViewerContent.vue
**Services & Stores:**
- src/services/litegraphService.ts
- src/services/load3dService.ts
- src/services/colorPaletteService.ts
- src/stores/maskEditorStore.ts
- src/stores/nodeDefStore.ts
- src/platform/settings/settingStore.ts
- src/platform/workflow/management/stores/workflowStore.ts
**Composables & Utils:**
- src/composables/node/useWatchWidget.ts
- src/composables/useCanvasDrop.ts
- src/utils/widgetPropFilter.ts
- src/utils/queueDisplay.ts
- src/utils/envUtil.ts
**Test Files:**
- browser_tests/fixtures/ComfyPage.ts
- browser_tests/fixtures/ws.ts
- browser_tests/tests/actionbar.spec.ts
-
src/workbench/extensions/manager/components/manager/skeleton/PackCardGridSkeleton.test.ts
- src/lib/litegraph/src/subgraph/subgraphUtils.test.ts
- src/components/rightSidePanel/shared.test.ts
- src/platform/cloud/subscription/composables/useSubscription.test.ts
-
src/platform/workflow/persistence/composables/useWorkflowPersistence.test.ts
**Scripts & Types:**
- scripts/i18n-types.ts (new shared module)
- scripts/diff-i18n.ts
- scripts/check-unused-i18n-keys.ts
- src/workbench/extensions/manager/types/conflictDetectionTypes.ts
- src/types/algoliaTypes.ts
- src/types/simplifiedWidget.ts
**Infrastructure:**
- src/lib/litegraph/src/litegraph.ts (added GraphOrSubgraph export)
- src/lib/litegraph/src/infrastructure/CustomEventTarget.ts
- src/platform/assets/services/assetService.ts
**Stories:**
- apps/desktop-ui/src/views/InstallView.stories.ts
- src/components/queue/job/JobDetailsPopover.stories.ts
**Extension Manager:**
- src/workbench/extensions/manager/composables/useConflictDetection.ts
- src/workbench/extensions/manager/composables/useManagerQueue.ts
- src/workbench/extensions/manager/services/comfyManagerService.ts
- src/workbench/extensions/manager/utils/conflictMessageUtil.ts
### Testing
- [x] All TypeScript type checking passes (`pnpm typecheck`)
- [x] ESLint passes without errors (`pnpm lint`)
- [x] Format checks pass (`pnpm format:check`)
- [x] Knip (unused exports) passes (`pnpm knip`)
- [x] Pre-commit and pre-push hooks pass
Part of the "Road to No Explicit Any" initiative.
### Previous PRs in this series:
- Part 2: #7401
- Part 3: #7935
- Part 4: #7970
- Part 5: #8064
- Part 6: #8083
- Part 7: #8092
- Part 8 Group 1: #8253
- Part 8 Group 2: #8258
- Part 8 Group 3: #8304
- Part 8 Group 4: #8314
- Part 8 Group 5: #8329
- Part 8 Group 6: #8344
- Part 8 Group 7: #8459
- Part 8 Group 8: #8496
- Part 9: #8498
- Part 10: #8499
---------
Co-authored-by: Comfy Org PR Bot <snomiao+comfy-pr@gmail.com>
Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
committed by
GitHub
parent
7f81e1afac
commit
90a701dd67
@@ -5,6 +5,7 @@ import PrimeVue from 'primevue/config'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { nextTick } from 'vue'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
import type { ComponentProps } from 'vue-component-type-helpers'
|
||||
|
||||
import enMessages from '@/locales/en/main.json' with { type: 'json' }
|
||||
|
||||
@@ -12,9 +13,11 @@ import GridSkeleton from './GridSkeleton.vue'
|
||||
import PackCardSkeleton from './PackCardSkeleton.vue'
|
||||
|
||||
describe('GridSkeleton', () => {
|
||||
const mountComponent = ({
|
||||
function mountComponent({
|
||||
props = {}
|
||||
}: Record<string, any> = {}): VueWrapper => {
|
||||
}: {
|
||||
props?: Partial<ComponentProps<typeof GridSkeleton>>
|
||||
} = {}): VueWrapper {
|
||||
const i18n = createI18n({
|
||||
legacy: false,
|
||||
locale: 'en',
|
||||
|
||||
@@ -19,6 +19,7 @@ import type {
|
||||
ConflictDetail,
|
||||
ConflictDetectionResponse,
|
||||
ConflictDetectionResult,
|
||||
ImportFailureMap,
|
||||
Node,
|
||||
NodeRequirements,
|
||||
SystemEnvironment
|
||||
@@ -336,7 +337,7 @@ export function useConflictDetection() {
|
||||
* Gets installed packages and checks each one for import failures using bulk API.
|
||||
* @returns Promise that resolves to import failure data
|
||||
*/
|
||||
async function fetchImportFailInfo(): Promise<Record<string, any>> {
|
||||
async function fetchImportFailInfo(): Promise<ImportFailureMap> {
|
||||
try {
|
||||
const comfyManagerService = useComfyManagerService()
|
||||
|
||||
@@ -362,7 +363,7 @@ export function useConflictDetection() {
|
||||
|
||||
if (bulkResult) {
|
||||
// Filter out null values (packages without import failures)
|
||||
const importFailures: Record<string, any> = {}
|
||||
const importFailures: ImportFailureMap = {}
|
||||
|
||||
Object.entries(bulkResult).forEach(([packageId, failInfo]) => {
|
||||
if (failInfo !== null) {
|
||||
@@ -389,10 +390,7 @@ export function useConflictDetection() {
|
||||
* @returns Array of conflict detection results for failed imports
|
||||
*/
|
||||
function detectImportFailConflicts(
|
||||
importFailInfo: Record<
|
||||
string,
|
||||
{ error?: string; traceback?: string } | null
|
||||
>
|
||||
importFailInfo: ImportFailureMap
|
||||
): ConflictDetectionResult[] {
|
||||
const results: ConflictDetectionResult[] = []
|
||||
if (!importFailInfo || typeof importFailInfo !== 'object') {
|
||||
|
||||
@@ -24,7 +24,7 @@ const MANAGER_WS_TASK_STARTED_NAME = 'cm-task-started'
|
||||
export const useManagerQueue = (
|
||||
taskHistory: Ref<ManagerTaskHistory>,
|
||||
taskQueue: Ref<ManagerTaskQueue>,
|
||||
installedPacks: Ref<Record<string, any>>
|
||||
installedPacks: Ref<Record<string, unknown>>
|
||||
) => {
|
||||
// Task queue state (read-only from server)
|
||||
const maxHistoryItems = ref(64)
|
||||
|
||||
@@ -156,7 +156,7 @@ export const useComfyManagerService = () => {
|
||||
const getImportFailInfo = async (signal?: AbortSignal) => {
|
||||
const errorContext = 'Fetching import failure information'
|
||||
|
||||
return executeRequest<any>(
|
||||
return executeRequest<Record<string, unknown>>(
|
||||
() => managerApiClient.get(ManagerRoute.IMPORT_FAIL_INFO, { signal }),
|
||||
{ errorContext }
|
||||
)
|
||||
|
||||
@@ -78,3 +78,16 @@ export interface ConflictDetectionResponse {
|
||||
results: ConflictDetectionResult[]
|
||||
detected_system_environment?: Partial<SystemEnvironment>
|
||||
}
|
||||
|
||||
/**
|
||||
* Detailed information about a Python import failure
|
||||
*/
|
||||
interface ImportFailureDetail {
|
||||
error?: string
|
||||
traceback?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Map of package IDs to their import failure information
|
||||
*/
|
||||
export type ImportFailureMap = Record<string, ImportFailureDetail | null>
|
||||
|
||||
@@ -10,7 +10,7 @@ import type { ConflictDetail } from '@/workbench/extensions/manager/types/confli
|
||||
*/
|
||||
export function getConflictMessage(
|
||||
conflict: ConflictDetail,
|
||||
t: (key: string, params?: Record<string, any>) => string
|
||||
t: (key: string, params?: Record<string, unknown>) => string
|
||||
): string {
|
||||
const messageKey = `manager.conflicts.conflictMessages.${conflict.type}`
|
||||
|
||||
@@ -53,7 +53,7 @@ export function getConflictMessage(
|
||||
*/
|
||||
export function getJoinedConflictMessages(
|
||||
conflicts: ConflictDetail[],
|
||||
t: (key: string, params?: Record<string, any>) => string,
|
||||
t: (key: string, params?: Record<string, unknown>) => string,
|
||||
separator = '; '
|
||||
): string {
|
||||
return conflicts
|
||||
|
||||
Reference in New Issue
Block a user