diff --git a/src/features/flights-map/calendarRange.test.ts b/src/features/flights-map/calendarRange.test.ts index 6bba7806..3c2e3fce 100644 --- a/src/features/flights-map/calendarRange.test.ts +++ b/src/features/flights-map/calendarRange.test.ts @@ -6,7 +6,7 @@ import { findNextEnabledDate, } from "./calendarRange.js"; -function yyyymmdd(d: Date): string { +function _yyyymmdd(d: Date): string { const y = d.getFullYear().toString(); const m = (d.getMonth() + 1).toString().padStart(2, "0"); const day = d.getDate().toString().padStart(2, "0"); diff --git a/src/features/flights-map/seo.test.ts b/src/features/flights-map/seo.test.ts index 87dff492..63a0cebf 100644 --- a/src/features/flights-map/seo.test.ts +++ b/src/features/flights-map/seo.test.ts @@ -47,7 +47,6 @@ describe("buildFlightsMapSeo", () => { const result = buildFlightsMapSeo(stubT, "ru", CANONICAL); expect(result.twitter).toBeDefined(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- test assertion guards above expect(result.twitter!.card).toBe("summary"); }); }); diff --git a/src/features/online-board/components/BoardDetailsHeader/BuyTicketButton.tsx b/src/features/online-board/components/BoardDetailsHeader/BuyTicketButton.tsx index 691e429c..ef10257a 100644 --- a/src/features/online-board/components/BoardDetailsHeader/BuyTicketButton.tsx +++ b/src/features/online-board/components/BoardDetailsHeader/BuyTicketButton.tsx @@ -11,8 +11,9 @@ export interface BuyTicketButtonProps { function buildBuyTicketUrl(flight: ISimpleFlight, locale: string): string { const legs = flight.routeType === "Direct" ? [flight.leg] : flight.legs; - const firstLeg = legs[0]!; - const lastLeg = legs[legs.length - 1]!; + const firstLeg = legs[0]; + const lastLeg = legs[legs.length - 1]; + if (!firstLeg || !lastLeg) return ""; const dep = firstLeg.departure.scheduled.airportCode; const arr = lastLeg.arrival.scheduled.airportCode; const depDate = parseISO(firstLeg.departure.times.scheduledDeparture.utc); diff --git a/src/features/online-board/components/FlightSchedule/FlightSchedule.tsx b/src/features/online-board/components/FlightSchedule/FlightSchedule.tsx index 118fac3c..45832af1 100644 --- a/src/features/online-board/components/FlightSchedule/FlightSchedule.tsx +++ b/src/features/online-board/components/FlightSchedule/FlightSchedule.tsx @@ -14,7 +14,7 @@ function formatLocalTime(iso: string | undefined): string { if (!iso) return ""; if (/^\d{2}:\d{2}$/.test(iso)) return iso; const match = /T(\d{2}:\d{2})/.exec(iso); - return match ? match[1]! : iso; + return match?.[1] ?? iso; } /** diff --git a/src/features/online-board/components/FlightsMiniList/FlightsMiniListItem.tsx b/src/features/online-board/components/FlightsMiniList/FlightsMiniListItem.tsx index b2b0c8c3..951e20a5 100644 --- a/src/features/online-board/components/FlightsMiniList/FlightsMiniListItem.tsx +++ b/src/features/online-board/components/FlightsMiniList/FlightsMiniListItem.tsx @@ -28,8 +28,9 @@ function getEndpoints(flight: ISimpleFlight): { dep: IFlightLeg["departure"]; ar if (flight.routeType === "Direct") { return { dep: flight.leg.departure, arr: flight.leg.arrival }; } - const firstLeg = flight.legs[0]!; - const lastLeg = flight.legs[flight.legs.length - 1]!; + const firstLeg = flight.legs[0]; + const lastLeg = flight.legs[flight.legs.length - 1]; + if (!firstLeg || !lastLeg) throw new Error("MultiLeg flight has no legs"); return { dep: firstLeg.departure, arr: lastLeg.arrival }; } diff --git a/src/features/online-board/components/OnlineBoardSearchPage.tsx b/src/features/online-board/components/OnlineBoardSearchPage.tsx index eb4a06f0..4ebe7734 100644 --- a/src/features/online-board/components/OnlineBoardSearchPage.tsx +++ b/src/features/online-board/components/OnlineBoardSearchPage.tsx @@ -62,7 +62,9 @@ function formatDateForApi(yyyymmdd: string): string { * rows. Matching Angular's OnlineBoardApiService.getFlightsByRoute. */ function addOneDayYyyymmdd(yyyymmdd: string): string { - const iso = yyyymmdd.includes("T") ? yyyymmdd.split("T")[0]! : yyyymmdd; + const iso = yyyymmdd.includes("T") + ? yyyymmdd.split("T")[0] ?? yyyymmdd + : yyyymmdd; let year: number, month: number, day: number; if (iso.includes("-")) { const [y, m, d] = iso.split("-"); diff --git a/src/features/online-board/components/details-panels/ServicesPanel.tsx b/src/features/online-board/components/details-panels/ServicesPanel.tsx index 593af13c..eda221d5 100644 --- a/src/features/online-board/components/details-panels/ServicesPanel.tsx +++ b/src/features/online-board/components/details-panels/ServicesPanel.tsx @@ -36,7 +36,7 @@ export const ServicesPanel: FC = ({ services }) => { const idNumeric = typeof svc.id === "string" ? Number(svc.id) : svc.id; const iconName = SERVICE_ICON_MAP[idNumeric] ?? SERVICE_ICON_FALLBACK; const iconSrc = - ICON_BY_NAME[iconName] ?? ICON_BY_NAME[SERVICE_ICON_FALLBACK]!; + ICON_BY_NAME[iconName] ?? ICON_BY_NAME[SERVICE_ICON_FALLBACK] ?? ""; const alt = svc.title ?? `service-${svc.id}`; const img = ( { const result = buildOnlineBoardStartSeo(stubT, "ru", CANONICAL); expect(result.twitter).toBeDefined(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- test assertion guards above expect(result.twitter!.card).toBe("summary"); }); }); diff --git a/src/features/schedule/ScheduleDetailsCatchAllRoute.tsx b/src/features/schedule/ScheduleDetailsCatchAllRoute.tsx index 3a8348e4..8031b7a3 100644 --- a/src/features/schedule/ScheduleDetailsCatchAllRoute.tsx +++ b/src/features/schedule/ScheduleDetailsCatchAllRoute.tsx @@ -14,7 +14,6 @@ import { lazy, Suspense } from "react"; import { useParams } from "@modern-js/runtime/router"; -import { useTranslation } from "@/i18n/provider.js"; import { parseFlightUrlParams } from "@/features/online-board/url.js"; import { FlightListSkeleton } from "@/ui/flights/FlightListSkeleton.js"; import { ErrorPage } from "@/ui/errors/ErrorPage.js"; @@ -55,7 +54,6 @@ function parseFlightSegments(segments: string[]): IScheduleFlightId[] { } export default function ScheduleDetailsCatchAllRoute(): JSX.Element { - const { t } = useTranslation(); const routeParams = useParams<{ "*": string; lang: string }>(); const locale = routeParams.lang ?? "ru-ru"; const canonicalOrigin = getEnv().PROD_ORIGIN; diff --git a/src/features/schedule/api.test.ts b/src/features/schedule/api.test.ts index 8ab33590..b887ddc5 100644 --- a/src/features/schedule/api.test.ts +++ b/src/features/schedule/api.test.ts @@ -39,7 +39,7 @@ function extractUrl(mockFetch: ReturnType): URL { return new URL(call[0]); } -function extractBody(mockFetch: ReturnType): unknown { +function _extractBody(mockFetch: ReturnType): unknown { const call = mockFetch.mock.calls[0] as [string, RequestInit]; return JSON.parse(call[1].body as string); } diff --git a/src/features/schedule/api.ts b/src/features/schedule/api.ts index 068ca069..07cdc2be 100644 --- a/src/features/schedule/api.ts +++ b/src/features/schedule/api.ts @@ -144,7 +144,9 @@ function parseCalendarDays(days: string, baseDate: string): string[] { function bitmaskToDates(bitmask: string, baseDate: string): string[] { // baseDate is yyyy-MM-dd (possibly with Txx:xx:xx suffix). - const iso = baseDate.includes("T") ? baseDate.split("T")[0]! : baseDate; + const iso = baseDate.includes("T") + ? baseDate.split("T")[0] ?? baseDate + : baseDate; const [y, m, d] = iso.split("-"); if (!y || !m || !d) return []; const cursor = new Date(Number(y), Number(m) - 1, Number(d)); diff --git a/src/features/schedule/components/ScheduleDetailsPage.tsx b/src/features/schedule/components/ScheduleDetailsPage.tsx index 62dd9021..33947be2 100644 --- a/src/features/schedule/components/ScheduleDetailsPage.tsx +++ b/src/features/schedule/components/ScheduleDetailsPage.tsx @@ -44,8 +44,9 @@ function formatApiDate(yyyymmdd: string): string { /** * Extract legs from a flight (handles both Direct and MultiLeg). + * Currently unused but kept for the planned full-route renderer. */ -function getLegs(flight: { routeType: string; leg?: IFlightLeg; legs?: IFlightLeg[] }): IFlightLeg[] { +function _getLegs(flight: { routeType: string; leg?: IFlightLeg; legs?: IFlightLeg[] }): IFlightLeg[] { if (flight.routeType === "Direct" && "leg" in flight && flight.leg) { return [flight.leg]; } diff --git a/src/features/schedule/seo.test.ts b/src/features/schedule/seo.test.ts index e55d5fa0..61f8366c 100644 --- a/src/features/schedule/seo.test.ts +++ b/src/features/schedule/seo.test.ts @@ -52,7 +52,6 @@ describe("buildScheduleStartSeo", () => { const result = buildScheduleStartSeo(stubT, "ru", CANONICAL); expect(result.twitter).toBeDefined(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- test assertion guards above expect(result.twitter!.card).toBe("summary"); }); }); diff --git a/src/shared/hooks/useAppSettings.ts b/src/shared/hooks/useAppSettings.ts index de351945..de3dfb89 100644 --- a/src/shared/hooks/useAppSettings.ts +++ b/src/shared/hooks/useAppSettings.ts @@ -22,8 +22,8 @@ function parsePattern( ): number { if (!value) return fallback; const match = pattern.exec(value); - if (!match) return fallback; - return parseInt(match[1]!, 10); + if (!match?.[1]) return fallback; + return parseInt(match[1], 10); } function parseDays(value: string | undefined, fallback: number): number { diff --git a/src/shared/seo/json-ld.test.ts b/src/shared/seo/json-ld.test.ts index 978e4ed1..d2f89af4 100644 --- a/src/shared/seo/json-ld.test.ts +++ b/src/shared/seo/json-ld.test.ts @@ -75,7 +75,6 @@ describe("JsonLdRenderer", () => { const match = html.match(/]*>([\s\S]*?)<\/script>/); expect(match).not.toBeNull(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- test assertion already guards const json = match![1]!.replace(/\\u003c/g, "<"); const parsed = JSON.parse(json); expect(parsed["@context"]).toBe("https://schema.org"); diff --git a/src/shared/utils/datetime/index.ts b/src/shared/utils/datetime/index.ts index 50028ad2..0566e077 100644 --- a/src/shared/utils/datetime/index.ts +++ b/src/shared/utils/datetime/index.ts @@ -92,7 +92,7 @@ export function formatLocalTime(iso: string): string { const full = ISO_OFFSET_RE.exec(iso); if (full) return `${full[4]}:${full[5]}`; const bare = BARE_HH_MM_RE.exec(iso); - if (bare) return `${bare[1]!.padStart(2, "0")}:${bare[2]}`; + if (bare?.[1] && bare[2]) return `${bare[1].padStart(2, "0")}:${bare[2]}`; return formatTime(iso); // fall back to Date-based formatter } diff --git a/src/ui/city-autocomplete/buildCountryCityRows.ts b/src/ui/city-autocomplete/buildCountryCityRows.ts index e9d3c7f0..e8fbe9b0 100644 --- a/src/ui/city-autocomplete/buildCountryCityRows.ts +++ b/src/ui/city-autocomplete/buildCountryCityRows.ts @@ -56,7 +56,8 @@ export function buildCountryCityRows( let firstRow = true; let i = 0; while (i < cities.length) { - const city1 = cities[i]!; + const city1 = cities[i]; + if (!city1) break; const multiAirport = city1.airports.length > 1; if (multiAirport) {