From 65372628a1f095f5245024965c91af96d4a500fd Mon Sep 17 00:00:00 2001 From: Aleksandr Penskoi Date: Wed, 18 Mar 2026 13:45:22 +0100 Subject: [PATCH] Narrow FieldSlicing discriminator type from string to literal union --- src/typeschema/core/field-builder.ts | 15 ++++++++++++--- src/typeschema/types.ts | 4 +++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/typeschema/core/field-builder.ts b/src/typeschema/core/field-builder.ts index 1334f3b3d..b554de62c 100644 --- a/src/typeschema/core/field-builder.ts +++ b/src/typeschema/core/field-builder.ts @@ -10,6 +10,7 @@ import type { CodegenLog } from "@root/utils/log"; import { packageMetaToFhir } from "@typeschema/types"; import type { BindingIdentifier, + DiscriminatorType, EnumDefinition, Field, FieldSlice, @@ -199,8 +200,16 @@ const computeTypeDiscriminatorMatch = ( * Used when a slice has an empty match but the discriminator values are nested deeper * (e.g., component slices in BP where the discriminator crosses a nested slicing boundary). */ +const validDiscriminatorTypes = new Set(["value", "exists", "pattern", "type", "profile"]); + +// TODO: Update type in FHIR Schema to prevent this casting. +const toDiscriminators = ( + raw: { type: string; path: string }[] | undefined, +): { type: DiscriminatorType; path: string }[] => + (raw ?? []).filter((d) => validDiscriminatorTypes.has(d.type)) as { type: DiscriminatorType; path: string }[]; + const computeMatchFromSchema = ( - discriminators: Array<{ type?: string; path: string }>, + discriminators: { type: DiscriminatorType; path: string }[], schema: FHIRSchemaElement | undefined, ): Record | undefined => { if (!schema || !discriminators || discriminators.length === 0) return undefined; @@ -230,7 +239,7 @@ const buildSlicing = (element: FHIRSchemaElement): FieldSlicing | undefined => { min: slice.min, max: slice.max, match: isEmptyMatch(slice.match) - ? computeMatchFromSchema(slicing.discriminator ?? [], slice.schema) + ? computeMatchFromSchema(toDiscriminators(slicing.discriminator), slice.schema) : (slice.match as Record | undefined), required, excluded, @@ -239,7 +248,7 @@ const buildSlicing = (element: FHIRSchemaElement): FieldSlicing | undefined => { } return { - discriminator: slicing.discriminator, + discriminator: toDiscriminators(slicing.discriminator), rules: slicing.rules, ordered: slicing.ordered, slices: Object.keys(slices).length > 0 ? slices : undefined, diff --git a/src/typeschema/types.ts b/src/typeschema/types.ts index 748243268..013affaae 100644 --- a/src/typeschema/types.ts +++ b/src/typeschema/types.ts @@ -211,8 +211,10 @@ export interface ProfileTypeSchema { nested?: NestedType[]; } +export type DiscriminatorType = "value" | "exists" | "pattern" | "type" | "profile"; + export interface FieldSlicing { - discriminator?: Array<{ type?: string; path: string }>; + discriminator?: { type: DiscriminatorType; path: string }[]; rules?: string; ordered?: boolean; slices?: Record;