fix(web): typecheck stricti per build di produzione

Quattro fix di tipi che emergono solo durante `next build` (con Next.js che esegue typecheck stretto su tutta l'app), pre-esistenti su main:

- `fast-timer.tsx`: l'omitted-vs-undefined di `exactOptionalPropertyTypes`
  rifiuta `{other: undefined}` per un campo opzionale. Costruisco l'oggetto
  symptoms condizionalmente.
- `plan-week.tsx`: `slots[0]` con `noUncheckedIndexedAccess` è `Slot |
  undefined`. Optional chaining `slots[0]?.meal`.
- `profile-form.tsx` e `weight-entry-form.tsx`: il mismatch Zod 3 + RHF
  + `exactOptionalPropertyTypes` sul tipo del Resolver è noto e non sistemabile
  senza upgrade. Cast locale del solo zodResolver, runtime invariato.

Lint pulito, 99/99 test verdi, `next build` ok in locale.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
lucianoandClaude Opus 4.7 committed 2026-05-07 13:49:52 +02:00
1 parent d98f95b7ca
commit e76074869b
4 files changed
+18 -6

No files matched your search

@@ -257,13 +257,15 @@ function SymptomsDiary({ event }: { event: FastEventRow }) {
function save(): void {
startTransition(async () => {
setSaved(false);
const result = await updateFastSymptoms(event.id, {
const symptoms: Parameters<typeof updateFastSymptoms>[1] = {
headache,
energy,
hunger,
clarity,
other: other.trim() || undefined,
});
};
const trimmedOther = other.trim();
if (trimmedOther) symptoms.other = trimmedOther;
const result = await updateFastSymptoms(event.id, symptoms);
if (result.ok) {
setSaved(true);
window.setTimeout(() => setSaved(false), 2500);
+1 -1
View File
@@ -139,7 +139,7 @@ export function PlanWeek({
// Nessuno slot → giorno di digiuno completo (ESE_24).
const isFastingDay = slots.length === 0;
// Solo CENA con dailyKcal ridotto → giorno "leggero" del 5:2.
const isLightDay = !isFastingDay && slots.length === 1 && slots[0].meal === 'CENA';
const isLightDay = !isFastingDay && slots.length === 1 && slots[0]?.meal === 'CENA';
return (
<section key={dayKey} aria-labelledby={`day-${dayKey}`} className="space-y-5">
@@ -1,6 +1,11 @@
'use client';
import { zodResolver } from '@hookform/resolvers/zod';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
import { zodResolver as zodResolverRaw } from '@hookform/resolvers/zod';
// Cast: zod 3.x + RHF + exactOptionalPropertyTypes generano un mismatch noto;
// il resolver runtime funziona, è solo un'incompatibilità sui tipi opzionali.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const zodResolver: any = zodResolverRaw;
import {
ACTIVITY_LEVELS,
DIET_HISTORIES,
@@ -1,6 +1,11 @@
'use client';
import { zodResolver } from '@hookform/resolvers/zod';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
import { zodResolver as zodResolverRaw } from '@hookform/resolvers/zod';
// Cast: zod 3.x + RHF + exactOptionalPropertyTypes generano un mismatch noto;
// il resolver runtime funziona, è solo un'incompatibilità sui tipi opzionali.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const zodResolver: any = zodResolverRaw;
import { weightEntryInputSchema, type WeightEntryInput } from '@ketopath/shared';
import { useTranslations } from 'next-intl';
import { useState } from 'react';