Conversation
📝 WalkthroughWalkthroughA type-safety pass: multiple Changes
Possibly related PRs
Suggested reviewers
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Replace `any` with proper TypeScript types across multiple files:
- widgetInputs.ts: remove unnecessary `as any` cast
- auth.ts: use `Record<string, unknown>` and Sentry types
- MixpanelTelemetryProvider.ts: use `AuditLog[]` type
- workflowStore.ts: use `typeof ComfyWorkflow` constructor type
- app.ts: use `ResultItem[]` for Clipspace images
- colorPaletteService.ts: use `Object.assign` instead of `as any`
- customerEventsService.ts: use `unknown` instead of `any`
- load3dService.ts: add proper interface types for Load3D nodes
- comfy.ts: extend Object for ComfyExtension interface
- litegraph-augmentation.d.ts: use `TWidgetValue[]` type
- envUtil.ts: add ElectronWindow interface
- comfyManagerStore.ts: type event as `CustomEvent<{ ui_id?: string }>`
8b837e5 to
b13f5d5
Compare
🎨 Storybook Build Status✅ Build completed successfully! ⏰ Completed at: 02/02/2026, 12:26:36 PM UTC 🔗 Links🎉 Your Storybook is ready for review! |
🎭 Playwright Tests: ✅ PassedResults: 507 passed, 0 failed, 0 flaky, 8 skipped (Total: 515) 📊 Browser Reports
|
Bundle Size ReportSummary
Category Glance Per-category breakdownApp Entry Points — 26 kB (baseline 26 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 978 kB (baseline 978 kB) • ⚪ 0 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed Views & Navigation — 80.7 kB (baseline 80.7 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 9 added / 9 removed Panels & Settings — 471 kB (baseline 471 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 12 added / 12 removed User & Accounts — 3.94 kB (baseline 3.94 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 3 added / 3 removed Editors & Dialogs — 2.89 kB (baseline 2.89 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 2 added / 2 removed UI Components — 33.7 kB (baseline 33.7 kB) • ⚪ 0 BReusable component library chunks
Status: 4 added / 4 removed Data & Services — 2.72 MB (baseline 2.72 MB) • 🔴 +102 BStores, services, APIs, and repositories
Status: 8 added / 8 removed Utilities & Hooks — 25.3 kB (baseline 25.3 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 7 added / 7 removed Vendor & Third-Party — 10.7 MB (baseline 10.7 MB) • ⚪ 0 BExternal libraries and shared vendor chunks
Other — 7.17 MB (baseline 7.17 MB) • ⚪ 0 BBundles that do not match a named category
Status: 36 added / 36 removed |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/services/customerEventsService.ts (1)
125-135: 🧹 Nitpick | 🔵 TrivialGood change from
anytounknown.This aligns with the coding guidelines to avoid
any. The type narrowing viatypeofchecks works correctly withunknown.Consider adding an explicit return type and converting the fallback to string for consistency, since this value is used in string interpolation at line 162.
💡 Optional: explicit return type and safer fallback
- function formatJsonValue(value: unknown) { + function formatJsonValue(value: unknown): string | number { if (typeof value === 'number') { // Format numbers with commas and decimals if needed return value.toLocaleString() } if (typeof value === 'string' && value.match(/^\d{4}-\d{2}-\d{2}/)) { // Format dates nicely return new Date(value).toLocaleString() } - return value + return String(value) }
🤖 Fix all issues with AI agents
In `@src/services/load3dService.ts`:
- Around line 10-14: You’ve duplicated the SceneConfig interface locally;
replace the local definition in load3dService.ts with an import of the canonical
SceneConfig interface from the project’s load3d interfaces module so you use the
full, single source of truth (including showGrid, backgroundColor,
backgroundImage, backgroundRenderMode); update the import statements to import
SceneConfig and remove the local interface declaration to prevent drift.
| // Type definitions for Load3D node | ||
| interface SceneConfig { | ||
| backgroundImage?: string | ||
| [key: string]: unknown | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if SceneConfig exists in the extensions directory
fd -t f "interfaces.ts" | head -20Repository: Comfy-Org/ComfyUI_frontend
Length of output: 146
🏁 Script executed:
#!/bin/bash
# Search for all SceneConfig interface definitions in the codebase
rg "interface SceneConfig" -A 5Repository: Comfy-Org/ComfyUI_frontend
Length of output: 775
🏁 Script executed:
#!/bin/bash
# Check the current state of load3dService.ts around lines 10-14
sed -n '1,30p' src/services/load3dService.tsRepository: Comfy-Org/ComfyUI_frontend
Length of output: 970
Consider importing the existing SceneConfig interface instead of defining a local duplicate.
There's already a SceneConfig interface defined in src/extensions/core/load3d/interfaces.ts with more complete properties (showGrid, backgroundColor, backgroundImage, backgroundRenderMode). The local definition here is a subset that may drift out of sync.
♻️ Proposed refactor to use the existing interface
-// Type definitions for Load3D node
-interface SceneConfig {
- backgroundImage?: string
- [key: string]: unknown
-}
+import type { SceneConfig } from '@/extensions/core/load3d/interfaces'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Type definitions for Load3D node | |
| interface SceneConfig { | |
| backgroundImage?: string | |
| [key: string]: unknown | |
| } | |
| import type { SceneConfig } from '@/extensions/core/load3d/interfaces' |
🤖 Prompt for AI Agents
In `@src/services/load3dService.ts` around lines 10 - 14, You’ve duplicated the
SceneConfig interface locally; replace the local definition in load3dService.ts
with an import of the canonical SceneConfig interface from the project’s load3d
interfaces module so you use the full, single source of truth (including
showGrid, backgroundColor, backgroundImage, backgroundRenderMode); update the
import statements to import SceneConfig and remove the local interface
declaration to prevent drift.
…the `SceneConfig` interface, and make `electronAPI` non-optional in the `ElectronWindow` type.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@src/services/load3dService.ts`:
- Line 19: viewerInstances is typed as Map<NodeId, any>, which breaks the "no
any" rule; update the map to use a concrete viewer instance type (or Map<NodeId,
unknown> if the concrete type is not yet defined) and propagate that type from
the factory/hook that creates it (useLoad3dViewer) by exporting/annotating its
return type so the map and consumers are strongly typed; locate viewerInstances
and the useLoad3dViewer function and replace the any with the appropriate
interface/class (or unknown) and adjust call sites to cast/assert to the
concrete viewer type or update their signatures to accept the new type.
In `@src/utils/envUtil.ts`:
- Around line 3-6: ElectronWindow currently marks electronAPI as required and
the electronAPI() helper asserts it non-null; change the types so electronAPI is
optional and electronAPI() returns ElectronAPI | undefined, then update call
sites to handle undefined (preserving guarded calls using isElectron()).
Concretely, modify the ElectronWindow type to make electronAPI?: ElectronAPI,
change the electronAPI() function signature/return to ElectronAPI | undefined,
and ensure places like electronDownloadStore.ts rely on isElectron() before
using the returned value or otherwise null-check the result.
| syncLoad3dConfig?: () => void | ||
| } | ||
|
|
||
| const viewerInstances = new Map<NodeId, any>() |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Remaining any type should be addressed.
This PR aims to remove explicit any usages, but viewerInstances still uses Map<NodeId, any>. Consider typing the return value of useLoad3dViewer or using unknown as a safer alternative.
♻️ Proposed refactor
-const viewerInstances = new Map<NodeId, any>()
+const viewerInstances = new Map<NodeId, ReturnType<typeof useLoad3dViewer>>()As per coding guidelines: "NEVER use any type - use proper TypeScript types".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const viewerInstances = new Map<NodeId, any>() | |
| const viewerInstances = new Map<NodeId, ReturnType<typeof useLoad3dViewer>>() |
🤖 Prompt for AI Agents
In `@src/services/load3dService.ts` at line 19, viewerInstances is typed as
Map<NodeId, any>, which breaks the "no any" rule; update the map to use a
concrete viewer instance type (or Map<NodeId, unknown> if the concrete type is
not yet defined) and propagate that type from the factory/hook that creates it
(useLoad3dViewer) by exporting/annotating its return type so the map and
consumers are strongly typed; locate viewerInstances and the useLoad3dViewer
function and replace the any with the appropriate interface/class (or unknown)
and adjust call sites to cast/assert to the concrete viewer type or update their
signatures to accept the new type.
## Summary This PR removes `any` types from UI component files and replaces them with proper TypeScript types. ### Key Changes #### Type Safety Improvements - Replaced `any` with `unknown`, explicit types, or proper interfaces across UI components - Used `ComponentPublicInstance` with explicit method signatures for component refs - Used `Record<string, unknown>` for dynamic property access - Added generics for form components with flexible value types - Used `CSSProperties` for style objects ### Files Changed UI Components: - src/components/common/ComfyImage.vue - Used proper class prop type - src/components/common/DeviceInfo.vue - Used `string | number` for formatValue - src/components/common/FormItem.vue - Used `unknown` for model value - src/components/common/FormRadioGroup.vue - Added generic type parameter - src/components/common/TreeExplorer.vue - Used proper async function signature - src/components/custom/widget/WorkflowTemplateSelectorDialog.vue - Fixed duplicate import - src/components/graph/CanvasModeSelector.vue - Used `ComponentPublicInstance` for ref - src/components/node/NodePreview.vue - Changed `any` to `unknown` - src/components/queue/job/JobDetailsPopover.vue - Removed unnecessary casts - src/components/queue/job/JobFiltersBar.vue - Removed `as any` casts - src/platform/assets/components/MediaAssetContextMenu.vue - Added `ContextMenuInstance` type - src/renderer/extensions/minimap/MiniMapPanel.vue - Used `CSSProperties` - src/renderer/extensions/vueNodes/composables/useNodeTooltips.ts - Added `PrimeVueTooltipElement` interface - src/renderer/extensions/vueNodes/widgets/components/form/FormSelectButton.vue - Used `Record<string, unknown>` - src/workbench/extensions/manager/components/manager/infoPanel/tabs/DescriptionTabPanel.vue - Added `LicenseObject` interface ### Testing - All TypeScript type checking passes (`pnpm typecheck`) - Linting passes without errors (`pnpm lint`) 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 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8499-Road-to-No-Explicit-Any-Part-10-2f86d73d365081aab129f165c7d02434) by [Unito](https://www.unito.io)
## 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>
## 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>
Summary
This PR removes
anytypes from core source files and replaces them with proper TypeScript types.Key Changes
Type Safety Improvements
anywithunknown, explicit types, or proper interfaces across core filesSceneConfig,Load3DNode,ElectronWindowObject.assigninstead ofas anyfor dynamic property assignmentas anycasts with proper type assertionsFiles Changed
Source files:
as anycastRecord<string, unknown>and Sentry typesAuditLog[]typetypeof ComfyWorkflowconstructor typeResultItem[]for Clipspace imagesObject.assigninstead ofas anyunknowninstead ofanyTWidgetValue[]typeCustomEvent<{ ui_id?: string }>Testing
pnpm typecheck)pnpm lint)pnpm format)Part of the "Road to No Explicit Any" initiative.
Previous PRs in this series: