π Fix 'any' type usage β rebased type safety PR with conflict resolution#4098
π Fix 'any' type usage β rebased type safety PR with conflict resolution#4098clubanderson merged 1 commit intomainfrom
Conversation
Rebased the type safety PR (#4085) on current main to resolve merge conflicts with the component split (#4062). Also fixed 5 new type errors introduced by the anyβunknown change: - kubectlProxy.ts: guard optional waitReason with ?? '' - Marketplace.tsx: narrow unknown data with type guard before access Original changes (from Copilot): - 3 source files: any β unknown/proper types - 62 test files: remove {} as any spreads, use typed props Signed-off-by: Andrew Anderson <andy@clubanderson.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
β Deploy Preview for kubestellarconsole ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
π Hey @clubanderson β thanks for opening this PR!
This is an automated message. |
|
Thank you for your contribution! Your PR has been merged. Check out what's new:
Stay connected: Slack #kubestellar-dev | Multi-Cluster Survey |
There was a problem hiding this comment.
Pull request overview
Rebases and reapplies prior type-safety work by removing explicit any usage in key hooks/libs and updating many React component tests to pass typed props instead of {} as any.
Changes:
- Replaced
anywithunknown/ concrete interfaces inuseMarketplace,useNightlyE2EData, andkubectlProxy. - Added runtime/type guards where needed for
unknowndata access (notably marketplace dashboard install flow). - Updated a large set of unit tests to render components with valid typed props instead of
{} as any.
Reviewed changes
Copilot reviewed 66 out of 66 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/lib/kubectlProxy.ts | Replaces any[] pod parsing with a concrete RawPodItem interface and safer nullish handling. |
| web/src/hooks/useNightlyE2EData.ts | Uses NightlyGuideStatus / NightlyRun types in guide/run mapping. |
| web/src/hooks/useMarketplace.ts | Changes install result payload type from any to unknown. |
| web/src/components/marketplace/Marketplace.tsx | Adds guards/casts for unknown install result data when installing dashboards. |
| web/src/components/ui/tests/StatBlockModePicker.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/ui/tests/RotatingTip.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/ui/tests/ProgressRing.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/ui/tests/LogoWithStar.test.tsx | Removes {} as any in favor of default render. |
| web/src/components/ui/tests/FlashingValue.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/ui/tests/FeatureHintTooltip.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/ui/tests/ConsoleAIIcon.test.tsx | Removes {} as any in favor of default render. |
| web/src/components/ui/tests/CollapsibleSection.test.tsx | Replaces {} as any with explicit required props/children. |
| web/src/components/shared/tests/DashboardHeader.test.tsx | Replaces {} as any with explicit props, wrapped in router. |
| web/src/components/settings/sections/tests/ProfileSection.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/settings/sections/tests/GitHubTokenSection.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/settings/sections/tests/AISettingsSection.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/settings/sections/tests/AgentSection.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/settings/sections/tests/AgentBackendSettings.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/settings/sections/tests/AccessibilitySection.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/rewards/tests/CoinDisplay.test.tsx | Removes {} as any in favor of default render. |
| web/src/components/missions/browser/tests/EmptyState.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/missions/tests/ResolutionHistoryPanel.test.tsx | Removes {} as any in favor of default render. |
| web/src/components/mission-control/svg/tests/DependencyPath.test.tsx | Replaces {} as any with explicit props and SVG wrapper. |
| web/src/components/mission-control/svg/tests/BlueprintDefs.test.tsx | Replaces {} as any with explicit props and SVG wrapper. |
| web/src/components/layout/mission-sidebar/tests/TypingIndicator.test.tsx | Removes {} as any in favor of default render. |
| web/src/components/layout/tests/SnoozedCards.test.tsx | Removes {} as any in favor of default render. |
| web/src/components/drilldown/views/pod-drilldown/tests/PodOutputTab.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/drilldown/views/pod-drilldown/tests/PodLabelsTab.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/drilldown/views/pod-drilldown/tests/PodDeleteSection.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/drilldown/views/pod-drilldown/tests/PodAiAnalysis.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/drilldown/views/tests/ServiceAccountDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/SecretDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/ResourcesDrillDown.test.tsx | Replaces {} as any with data={{}}. |
| web/src/components/drilldown/views/tests/ReplicaSetDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/RBACDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/PodDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/NodeDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/NamespaceDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/MultiClusterSummaryDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/LogsDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/GPUNodeDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/GPUNamespaceDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/EventsDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/DeploymentDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/CostDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/ConfigMapDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/drilldown/views/tests/ComplianceDrillDown.test.tsx | Removes as any from typed data prop. |
| web/src/components/dashboard/tests/PostConnectBanner.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/clusters/add-cluster/tests/CopyButton.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/clusters/add-cluster/tests/ConnectTab.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/clusters/tests/EmptyClusterState.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/clusters/tests/CPUDetailModal.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/cards/rss/tests/RSSFeed.test.tsx | Removes {} as any render props. |
| web/src/components/cards/llmd/shared/tests/PortalTooltip.test.tsx | Replaces {} as any with explicit props/children. |
| web/src/components/cards/llmd/shared/tests/HorseshoeGauge.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/cards/insights/tests/InsightSourceBadge.test.tsx | Replaces {} as any with explicit props. |
| web/src/components/cards/deploy/tests/GitOpsDriftDetailModal.test.tsx | Replaces as any with null for nullable props. |
| web/src/components/cards/compliance/tests/PolicyViolationDetailModal.test.tsx | Replaces as any with null for nullable props. |
| web/src/components/cards/tests/TopPods.test.tsx | Removes {} as any render props. |
| web/src/components/cards/tests/ServiceImports.test.tsx | Removes {} as any render props. |
| web/src/components/cards/tests/ServiceExports.test.tsx | Removes {} as any render props. |
| web/src/components/cards/tests/SecurityIssues.test.tsx | Removes {} as any render props. |
| web/src/components/cards/tests/NamespaceRBAC.test.tsx | Removes {} as any render props. |
| web/src/components/cards/tests/DeploymentIssues.test.tsx | Removes {} as any render props. |
| web/src/components/cards/tests/CrossClusterPolicyComparison.test.tsx | Removes {} as any render props. |
| web/src/components/cards/tests/ClusterDropZone.test.tsx | Replaces {} as any with explicit props. |
| export interface InstallResult { | ||
| type: MarketplaceItemType | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| data?: any | ||
| data?: unknown | ||
| } |
There was a problem hiding this comment.
InstallResult is now unknown, but installItem() has a well-defined response shape per item type. Consider making InstallResult a discriminated union (e.g. card-preset/theme/dashboard) so callers can access typed fields (like dashboard cards) without Record<string, unknown> casts and runtime 'in' checks.
| const dashData = result.data as Record<string, unknown> | ||
| const cards = (Array.isArray(dashData.cards) ? dashData.cards : []) as unknown[] | ||
| try { | ||
| localStorage.setItem(`kubestellar-custom-dashboard-${item.id}-cards`, JSON.stringify(cards)) | ||
| } catch { /* non-critical */ } |
There was a problem hiding this comment.
This code has to downcast result.data to Record<string, unknown> and treat cards as unknown[], which largely defeats the type-safety goal of the PR. The backend POST /api/dashboards/import returns a DashboardWithCards payload (includes cards), but useMarketplace.installItem() currently types that call as { id: string }, forcing these casts. Align the installItem() return type with the actual API response and then remove the Record<string, unknown> / unknown[] casts here.
π Auto-Applying Copilot Code ReviewCopilot code review found 0 code suggestion(s) and 2 general comment(s). Also address these general comments:
Push all fixes in a single commit. Run Auto-generated by copilot-review-apply workflow. |
Summary
Rebases and fixes the type safety improvements from #4085 (which had merge conflicts with #4062).
anyβunknown/proper types (useMarketplace, useNightlyE2EData, kubectlProxy){} as anywith typed propsanyβunknownchange (optional field narrowing, unknown data guards)Supersedes #4085.
Test plan
tsc --noEmitpasses (verified locally)