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
Source: PRD-018 SC-2 audit, Type [C1] + [W2] + [C2].
C1: blunt
as ThemeModecasttemplate/src/widgets/health-bar/ui/HealthBar.svelte:97visstring(whatToggleGroup 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:
Or — better — parameterise
ToggleGroup<TValue>so the callback is(next: ThemeMode) => void.W2:
permissiontyped asstringtemplate/src/widgets/health-bar/ui/HealthBar.svelte:16Should be
$state<NotificationPermission>('default')(DOM lib type, union'default' | 'granted' | 'denied'). Then the comparisons at lines 43, 111, 114 become exhaustive.C2: legacy
$props<{...}>()syntaxtemplate/src/widgets/health-bar/ui/HealthBar.svelte:11Other migrated widgets use
interface Props { … }; let { … }: Props = $props();. HealthBar uses the legacy generic-argument form. Fix: lift to aPropsinterface likeFilters.svelte:10.Acceptance
npm run checkclean.as ThemeModeor generic-argument$props<>in the file.permissiontypedNotificationPermission.Audit traceability