Skip to content

[type-safety] HealthBar: drop as ThemeMode cast; type permission as NotificationPermission #93

@fedorovvvv

Description

@fedorovvvv

Source: PRD-018 SC-2 audit, Type [C1] + [W2] + [C2].

C1: blunt as ThemeMode cast

template/src/widgets/health-bar/ui/HealthBar.svelte:97

onValueChange={(v) => themeStore.setMode(v as ThemeMode)}

v is string (what ToggleGroup type="single" declares for its callback). If bits-ui ever fires '' (deselection) or any future value, themeStore.setMode('') becomes a runtime fault with no compile-time signal.

Fix:

onValueChange={(v) => {
  if (v === 'auto' || v === 'light' || v === 'dark') themeStore.setMode(v);
}}

Or — better — parameterise ToggleGroup<TValue> so the callback is (next: ThemeMode) => void.

W2: permission typed as string

template/src/widgets/health-bar/ui/HealthBar.svelte:16

let permission = $state<string>('default');

Should be $state<NotificationPermission>('default') (DOM lib type, union 'default' | 'granted' | 'denied'). Then the comparisons at lines 43, 111, 114 become exhaustive.

C2: legacy $props<{...}>() syntax

template/src/widgets/health-bar/ui/HealthBar.svelte:11

Other migrated widgets use interface Props { … }; let { … }: Props = $props();. HealthBar uses the legacy generic-argument form. Fix: lift to a Props interface like Filters.svelte:10.

Acceptance

  • npm run check clean.
  • No as ThemeMode or generic-argument $props<> in the file.
  • permission typed NotificationPermission.

Audit traceability

  • Reviewer: TypeScript-pro, score 7/10

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:appbugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions