ITADN

Narrow ResultEntry to a discriminated union in the webclient

#3199OpenCommanderStorm 创建于 2026-06-08
featureready-for-agent
C
CommanderStormcommented
## Parent #3198 ## What to build The webclient consumes the OpenAPI-generated `ResultEntry` shape, which declares `type: string` with optional per-variant fields (`title_de`, `title_en`, `upcoming`, `next_occurrence_at`, `parsed_id`, `subtext_bold`). The invariant "`upcoming` is populated iff `type === \"lecture\"`" lives only in JSDoc, so every consumer reasserts the same string check before touching variant fields (`SearchResultItem.vue`, `SearchResultItemLink.vue`, `AppSearchBar.vue`, `lectureRow.ts`, `entityPath.ts`, `pages/search.vue`, `NavigationSearchBar.vue`). Introduce a webclient-side TypeScript overlay that re-exports `ResultEntry` as a discriminated union keyed by `type`, with each variant carrying only its valid fields. The OpenAPI generator cannot synthesize this, so the generated `api_types/index.ts` is left untouched; the overlay is a separate module that consumers import instead of the raw `components["schemas"]["ResultEntry"]`. After this slice: - Every consumer imports the union; defensive `entry.upcoming ?? []` constructs collapse to direct access on the lecture variant. - `entry.type !== "lecture"` guards become TypeScript narrowings. - Search UI behaves identically across every variant (room, virtual_room, poi, building, site, address, lecture). ## Acceptance criteria - [ ] A discriminated-union overlay for `ResultEntry` exists and is imported by every consumer of the raw shape. - [ ] Variant fields are only visible on their valid variants; defensive optional chaining for those fields is removed. - [ ] `entityPath.ts:isRoutableEntityType` is either removed (subsumed by the union) or recast to operate over the narrowed type. - [ ] No consumer reaches past the discriminator with `as` casts. - [ ] `pnpm --dir webclient type-check` passes. - [ ] `pnpm --dir webclient lint` passes. - [ ] Search dropdown and `/search` page render results unchanged for every variant (manual verification in dev mode). ## Blocked by None - can start immediately.
0 条评论