diff --git a/examples/typescript-r4/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_bodyweight.ts b/examples/typescript-r4/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_bodyweight.ts index f02e6c45..58c57126 100644 --- a/examples/typescript-r4/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_bodyweight.ts +++ b/examples/typescript-r4/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_bodyweight.ts @@ -9,6 +9,9 @@ import type { Quantity } from "../../hl7-fhir-r4-core/Quantity"; import type { Reference } from "../../hl7-fhir-r4-core/Reference"; export type Observation_bodyweight_Category_VSCatSliceFlat = Omit; +export type Observation_bodyweight_Category_VSCatSliceFlatAll = Observation_bodyweight_Category_VSCatSliceFlat & { + readonly coding: [{ code: "vital-signs"; system: "http://terminology.hl7.org/CodeSystem/observation-category" }]; +} import { ensureProfile, @@ -17,7 +20,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, validateRequired, validateExcluded, validateFixedValue, @@ -38,7 +40,9 @@ export type observation_bodyweightProfileRaw = { export class observation_bodyweightProfile { static readonly canonicalUrl = "http://hl7.org/fhir/StructureDefinition/bodyweight"; - private static readonly VSCatSliceMatch: Record = {"coding":[{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}]}; + private static readonly VSCatSliceMatch: Record = { + "coding": [{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}], + } private resource: Observation; @@ -166,15 +170,15 @@ export class observation_bodyweightProfile { return this } - public getVSCat(mode: 'flat'): Observation_bodyweight_Category_VSCatSliceFlat | undefined; + public getVSCat(mode: 'flat'): Observation_bodyweight_Category_VSCatSliceFlatAll | undefined; public getVSCat(mode: 'raw'): CodeableConcept | undefined; - public getVSCat(): Observation_bodyweight_Category_VSCatSliceFlat | undefined; - public getVSCat (mode: 'flat' | 'raw' = 'flat'): Observation_bodyweight_Category_VSCatSliceFlat | CodeableConcept | undefined { + public getVSCat(): Observation_bodyweight_Category_VSCatSliceFlatAll | undefined; + public getVSCat (mode: 'flat' | 'raw' = 'flat'): Observation_bodyweight_Category_VSCatSliceFlatAll | CodeableConcept | undefined { const match = observation_bodyweightProfile.VSCatSliceMatch const item = getArraySlice(this.resource.category, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["coding"]) + return item as unknown as Observation_bodyweight_Category_VSCatSliceFlatAll } // Validation diff --git a/examples/typescript-r4/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_bp.ts b/examples/typescript-r4/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_bp.ts index 52f53ce9..677fbff6 100644 --- a/examples/typescript-r4/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_bp.ts +++ b/examples/typescript-r4/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_bp.ts @@ -9,8 +9,15 @@ import type { Quantity } from "../../hl7-fhir-r4-core/Quantity"; import type { Reference } from "../../hl7-fhir-r4-core/Reference"; export type Observation_bp_Category_VSCatSliceFlat = Omit; +export type Observation_bp_Category_VSCatSliceFlatAll = Observation_bp_Category_VSCatSliceFlat & { + readonly coding: [{ code: "vital-signs"; system: "http://terminology.hl7.org/CodeSystem/observation-category" }]; +} + export type Observation_bp_Component_SystolicBPSliceFlat = Omit & Quantity; +export type Observation_bp_Component_SystolicBPSliceFlatAll = Observation_bp_Component_SystolicBPSliceFlat; + export type Observation_bp_Component_DiastolicBPSliceFlat = Omit & Quantity; +export type Observation_bp_Component_DiastolicBPSliceFlatAll = Observation_bp_Component_DiastolicBPSliceFlat; import { ensureProfile, @@ -19,7 +26,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, wrapSliceChoice, unwrapSliceChoice, validateRequired, @@ -43,9 +49,15 @@ export type observation_bpProfileRaw = { export class observation_bpProfile { static readonly canonicalUrl = "http://hl7.org/fhir/StructureDefinition/bp"; - private static readonly VSCatSliceMatch: Record = {"coding":[{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}]}; - private static readonly SystolicBPSliceMatch: Record = {"code":{"coding":[{"code":"8480-6","system":"http://loinc.org"}]}}; - private static readonly DiastolicBPSliceMatch: Record = {"code":{"coding":[{"code":"8462-4","system":"http://loinc.org"}]}}; + private static readonly VSCatSliceMatch: Record = { + "coding": [{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}], + } + private static readonly SystolicBPSliceMatch: Record = { + "code": {"coding":[{"code":"8480-6","system":"http://loinc.org"}]}, + } + private static readonly DiastolicBPSliceMatch: Record = { + "code": {"coding":[{"code":"8462-4","system":"http://loinc.org"}]}, + } private resource: Observation; @@ -217,37 +229,37 @@ export class observation_bpProfile { return this } - public getVSCat(mode: 'flat'): Observation_bp_Category_VSCatSliceFlat | undefined; + public getVSCat(mode: 'flat'): Observation_bp_Category_VSCatSliceFlatAll | undefined; public getVSCat(mode: 'raw'): CodeableConcept | undefined; - public getVSCat(): Observation_bp_Category_VSCatSliceFlat | undefined; - public getVSCat (mode: 'flat' | 'raw' = 'flat'): Observation_bp_Category_VSCatSliceFlat | CodeableConcept | undefined { + public getVSCat(): Observation_bp_Category_VSCatSliceFlatAll | undefined; + public getVSCat (mode: 'flat' | 'raw' = 'flat'): Observation_bp_Category_VSCatSliceFlatAll | CodeableConcept | undefined { const match = observation_bpProfile.VSCatSliceMatch const item = getArraySlice(this.resource.category, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["coding"]) + return item as unknown as Observation_bp_Category_VSCatSliceFlatAll } - public getSystolicBP(mode: 'flat'): Observation_bp_Component_SystolicBPSliceFlat | undefined; + public getSystolicBP(mode: 'flat'): Observation_bp_Component_SystolicBPSliceFlatAll | undefined; public getSystolicBP(mode: 'raw'): ObservationComponent | undefined; - public getSystolicBP(): Observation_bp_Component_SystolicBPSliceFlat | undefined; - public getSystolicBP (mode: 'flat' | 'raw' = 'flat'): Observation_bp_Component_SystolicBPSliceFlat | ObservationComponent | undefined { + public getSystolicBP(): Observation_bp_Component_SystolicBPSliceFlatAll | undefined; + public getSystolicBP (mode: 'flat' | 'raw' = 'flat'): Observation_bp_Component_SystolicBPSliceFlatAll | ObservationComponent | undefined { const match = observation_bpProfile.SystolicBPSliceMatch const item = getArraySlice(this.resource.component, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["code"], "valueQuantity") + return unwrapSliceChoice(item, ["code"], "valueQuantity") } - public getDiastolicBP(mode: 'flat'): Observation_bp_Component_DiastolicBPSliceFlat | undefined; + public getDiastolicBP(mode: 'flat'): Observation_bp_Component_DiastolicBPSliceFlatAll | undefined; public getDiastolicBP(mode: 'raw'): ObservationComponent | undefined; - public getDiastolicBP(): Observation_bp_Component_DiastolicBPSliceFlat | undefined; - public getDiastolicBP (mode: 'flat' | 'raw' = 'flat'): Observation_bp_Component_DiastolicBPSliceFlat | ObservationComponent | undefined { + public getDiastolicBP(): Observation_bp_Component_DiastolicBPSliceFlatAll | undefined; + public getDiastolicBP (mode: 'flat' | 'raw' = 'flat'): Observation_bp_Component_DiastolicBPSliceFlatAll | ObservationComponent | undefined { const match = observation_bpProfile.DiastolicBPSliceMatch const item = getArraySlice(this.resource.component, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["code"], "valueQuantity") + return unwrapSliceChoice(item, ["code"], "valueQuantity") } // Validation diff --git a/examples/typescript-r4/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_vitalsigns.ts b/examples/typescript-r4/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_vitalsigns.ts index d8cb909d..a4c86d7d 100644 --- a/examples/typescript-r4/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_vitalsigns.ts +++ b/examples/typescript-r4/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_vitalsigns.ts @@ -8,6 +8,9 @@ import type { Period } from "../../hl7-fhir-r4-core/Period"; import type { Reference } from "../../hl7-fhir-r4-core/Reference"; export type Observation_vitalsigns_Category_VSCatSliceFlat = Omit; +export type Observation_vitalsigns_Category_VSCatSliceFlatAll = Observation_vitalsigns_Category_VSCatSliceFlat & { + readonly coding: [{ code: "vital-signs"; system: "http://terminology.hl7.org/CodeSystem/observation-category" }]; +} import { ensureProfile, @@ -16,7 +19,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, validateRequired, validateExcluded, validateFixedValue, @@ -38,7 +40,9 @@ export type observation_vitalsignsProfileRaw = { export class observation_vitalsignsProfile { static readonly canonicalUrl = "http://hl7.org/fhir/StructureDefinition/vitalsigns"; - private static readonly VSCatSliceMatch: Record = {"coding":[{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}]}; + private static readonly VSCatSliceMatch: Record = { + "coding": [{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}], + } private resource: Observation; @@ -159,15 +163,15 @@ export class observation_vitalsignsProfile { return this } - public getVSCat(mode: 'flat'): Observation_vitalsigns_Category_VSCatSliceFlat | undefined; + public getVSCat(mode: 'flat'): Observation_vitalsigns_Category_VSCatSliceFlatAll | undefined; public getVSCat(mode: 'raw'): CodeableConcept | undefined; - public getVSCat(): Observation_vitalsigns_Category_VSCatSliceFlat | undefined; - public getVSCat (mode: 'flat' | 'raw' = 'flat'): Observation_vitalsigns_Category_VSCatSliceFlat | CodeableConcept | undefined { + public getVSCat(): Observation_vitalsigns_Category_VSCatSliceFlatAll | undefined; + public getVSCat (mode: 'flat' | 'raw' = 'flat'): Observation_vitalsigns_Category_VSCatSliceFlatAll | CodeableConcept | undefined { const match = observation_vitalsignsProfile.VSCatSliceMatch const item = getArraySlice(this.resource.category, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["coding"]) + return item as unknown as Observation_vitalsigns_Category_VSCatSliceFlatAll } // Validation diff --git a/examples/typescript-r4/profile-bodyweight.test.ts b/examples/typescript-r4/profile-bodyweight.test.ts index 8de5b2ba..dac9b017 100644 --- a/examples/typescript-r4/profile-bodyweight.test.ts +++ b/examples/typescript-r4/profile-bodyweight.test.ts @@ -4,7 +4,11 @@ import { describe, expect, test } from "bun:test"; import type { Observation } from "./fhir-types/hl7-fhir-r4-core/Observation"; -import { observation_bodyweightProfile as bodyweightProfile } from "./fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_bodyweight"; +import { + observation_bodyweightProfile as bodyweightProfile, + type Observation_bodyweight_Category_VSCatSliceFlat as VSCatFlat, + type Observation_bodyweight_Category_VSCatSliceFlatAll as VSCatFlatAll, +} from "./fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_bodyweight"; describe("demo: create a bodyweight observation", () => { test("build a valid bodyweight resource step by step", () => { @@ -95,13 +99,12 @@ describe("demo: read a bodyweight observation from JSON", () => { // Code is a fixed value — auto-set by the profile, read-only (no setter) expect(profile.getCode()!.coding![0]!.code).toBe("29463-7"); - // Slice accessor strips discriminator keys (coding) by default — only user data remains - expect(profile.getVSCat()).toEqual({ text: "Vital Signs" }); - // Use "raw" mode to see the full element including discriminator - expect(profile.getVSCat("raw")!.coding).toEqual([ - { code: "vital-signs", system: "http://terminology.hl7.org/CodeSystem/observation-category" }, - ]); - expect(profile.getVSCat("raw")!.text).toBe("Vital Signs"); + // Slice getter returns SliceFlat — includes both user data and discriminator values + const vsCat = profile.getVSCat()!; + expect(vsCat).toEqual({ + text: "Vital Signs", + coding: [{ code: "vital-signs", system: "http://terminology.hl7.org/CodeSystem/observation-category" }], + }); }); }); @@ -123,13 +126,19 @@ describe("factory method equivalence", () => { }); describe("slice accessors", () => { - test("setVSCat merges discriminator and strips it in flat mode", () => { + test("setVSCat accepts SliceFlatInput, getVSCat returns SliceFlat", () => { const profile = bodyweightProfile.create({ status: "final", subject: { reference: "Patient/pt-1" } }); - profile.setVSCat({ text: "Vital Signs" }); - expect(profile.getVSCat()).toEqual({ text: "Vital Signs" }); - expect(profile.getVSCat("raw")!.coding).toBeDefined(); - expect(profile.getVSCat("raw")!.text).toBe("Vital Signs"); + // Setter accepts SliceFlatInput — only user-supplied fields, no discriminators + const input: VSCatFlat = { text: "Vital Signs" }; + profile.setVSCat(input); + + // Getter returns SliceFlatAll — includes discriminator values + user data + const flat: VSCatFlatAll = profile.getVSCat()!; + expect(flat).toEqual({ + text: "Vital Signs", + coding: [{ code: "vital-signs", system: "http://terminology.hl7.org/CodeSystem/observation-category" }], + }); }); test("setVSCat replaces existing slice element", () => { diff --git a/examples/typescript-us-core/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_vitalsigns.ts b/examples/typescript-us-core/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_vitalsigns.ts index d8cb909d..a4c86d7d 100644 --- a/examples/typescript-us-core/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_vitalsigns.ts +++ b/examples/typescript-us-core/fhir-types/hl7-fhir-r4-core/profiles/Observation_observation_vitalsigns.ts @@ -8,6 +8,9 @@ import type { Period } from "../../hl7-fhir-r4-core/Period"; import type { Reference } from "../../hl7-fhir-r4-core/Reference"; export type Observation_vitalsigns_Category_VSCatSliceFlat = Omit; +export type Observation_vitalsigns_Category_VSCatSliceFlatAll = Observation_vitalsigns_Category_VSCatSliceFlat & { + readonly coding: [{ code: "vital-signs"; system: "http://terminology.hl7.org/CodeSystem/observation-category" }]; +} import { ensureProfile, @@ -16,7 +19,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, validateRequired, validateExcluded, validateFixedValue, @@ -38,7 +40,9 @@ export type observation_vitalsignsProfileRaw = { export class observation_vitalsignsProfile { static readonly canonicalUrl = "http://hl7.org/fhir/StructureDefinition/vitalsigns"; - private static readonly VSCatSliceMatch: Record = {"coding":[{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}]}; + private static readonly VSCatSliceMatch: Record = { + "coding": [{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}], + } private resource: Observation; @@ -159,15 +163,15 @@ export class observation_vitalsignsProfile { return this } - public getVSCat(mode: 'flat'): Observation_vitalsigns_Category_VSCatSliceFlat | undefined; + public getVSCat(mode: 'flat'): Observation_vitalsigns_Category_VSCatSliceFlatAll | undefined; public getVSCat(mode: 'raw'): CodeableConcept | undefined; - public getVSCat(): Observation_vitalsigns_Category_VSCatSliceFlat | undefined; - public getVSCat (mode: 'flat' | 'raw' = 'flat'): Observation_vitalsigns_Category_VSCatSliceFlat | CodeableConcept | undefined { + public getVSCat(): Observation_vitalsigns_Category_VSCatSliceFlatAll | undefined; + public getVSCat (mode: 'flat' | 'raw' = 'flat'): Observation_vitalsigns_Category_VSCatSliceFlatAll | CodeableConcept | undefined { const match = observation_vitalsignsProfile.VSCatSliceMatch const item = getArraySlice(this.resource.category, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["coding"]) + return item as unknown as Observation_vitalsigns_Category_VSCatSliceFlatAll } // Validation diff --git a/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Extension_USCoreEthnicityExtension.ts b/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Extension_USCoreEthnicityExtension.ts index f69e5c62..4794ccf3 100644 --- a/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Extension_USCoreEthnicityExtension.ts +++ b/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Extension_USCoreEthnicityExtension.ts @@ -6,8 +6,15 @@ import type { Coding } from "../../hl7-fhir-r4-core/Coding"; import type { Extension } from "../../hl7-fhir-r4-core/Extension"; export type USCoreEthnicityExtension_Extension_OmbCategorySliceFlat = Omit & Coding; +export type USCoreEthnicityExtension_Extension_OmbCategorySliceFlatAll = USCoreEthnicityExtension_Extension_OmbCategorySliceFlat; + export type USCoreEthnicityExtension_Extension_DetailedSliceFlat = Omit & Coding; +export type USCoreEthnicityExtension_Extension_DetailedSliceFlatAll = USCoreEthnicityExtension_Extension_DetailedSliceFlat; + export type USCoreEthnicityExtension_Extension_TextSliceFlat = Omit; +export type USCoreEthnicityExtension_Extension_TextSliceFlatAll = USCoreEthnicityExtension_Extension_TextSliceFlat & { + readonly url: "text"; +} import { isRawExtensionInput, @@ -16,7 +23,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, wrapSliceChoice, unwrapSliceChoice, isExtension, @@ -203,37 +209,37 @@ export class USCoreEthnicityExtensionProfile { return this } - public getExtensionOmbCategory(mode: 'flat'): USCoreEthnicityExtension_Extension_OmbCategorySliceFlat | undefined; + public getExtensionOmbCategory(mode: 'flat'): USCoreEthnicityExtension_Extension_OmbCategorySliceFlatAll | undefined; public getExtensionOmbCategory(mode: 'raw'): Extension | undefined; - public getExtensionOmbCategory(): USCoreEthnicityExtension_Extension_OmbCategorySliceFlat | undefined; - public getExtensionOmbCategory (mode: 'flat' | 'raw' = 'flat'): USCoreEthnicityExtension_Extension_OmbCategorySliceFlat | Extension | undefined { + public getExtensionOmbCategory(): USCoreEthnicityExtension_Extension_OmbCategorySliceFlatAll | undefined; + public getExtensionOmbCategory (mode: 'flat' | 'raw' = 'flat'): USCoreEthnicityExtension_Extension_OmbCategorySliceFlatAll | Extension | undefined { const match = USCoreEthnicityExtensionProfile.ombCategorySliceMatch const item = getArraySlice(this.resource.extension, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["url"], "valueCoding") + return unwrapSliceChoice(item, ["url"], "valueCoding") } - public getExtensionDetailed(mode: 'flat'): USCoreEthnicityExtension_Extension_DetailedSliceFlat | undefined; + public getExtensionDetailed(mode: 'flat'): USCoreEthnicityExtension_Extension_DetailedSliceFlatAll | undefined; public getExtensionDetailed(mode: 'raw'): Extension | undefined; - public getExtensionDetailed(): USCoreEthnicityExtension_Extension_DetailedSliceFlat | undefined; - public getExtensionDetailed (mode: 'flat' | 'raw' = 'flat'): USCoreEthnicityExtension_Extension_DetailedSliceFlat | Extension | undefined { + public getExtensionDetailed(): USCoreEthnicityExtension_Extension_DetailedSliceFlatAll | undefined; + public getExtensionDetailed (mode: 'flat' | 'raw' = 'flat'): USCoreEthnicityExtension_Extension_DetailedSliceFlatAll | Extension | undefined { const match = USCoreEthnicityExtensionProfile.detailedSliceMatch const item = getArraySlice(this.resource.extension, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["url"], "valueCoding") + return unwrapSliceChoice(item, ["url"], "valueCoding") } - public getExtensionText(mode: 'flat'): USCoreEthnicityExtension_Extension_TextSliceFlat | undefined; + public getExtensionText(mode: 'flat'): USCoreEthnicityExtension_Extension_TextSliceFlatAll | undefined; public getExtensionText(mode: 'raw'): Extension | undefined; - public getExtensionText(): USCoreEthnicityExtension_Extension_TextSliceFlat | undefined; - public getExtensionText (mode: 'flat' | 'raw' = 'flat'): USCoreEthnicityExtension_Extension_TextSliceFlat | Extension | undefined { + public getExtensionText(): USCoreEthnicityExtension_Extension_TextSliceFlatAll | undefined; + public getExtensionText (mode: 'flat' | 'raw' = 'flat'): USCoreEthnicityExtension_Extension_TextSliceFlatAll | Extension | undefined { const match = USCoreEthnicityExtensionProfile.textSliceMatch const item = getArraySlice(this.resource.extension, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["url"]) + return item as unknown as USCoreEthnicityExtension_Extension_TextSliceFlatAll } // Validation diff --git a/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Extension_USCoreRaceExtension.ts b/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Extension_USCoreRaceExtension.ts index 03e5cc6d..da6e4171 100644 --- a/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Extension_USCoreRaceExtension.ts +++ b/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Extension_USCoreRaceExtension.ts @@ -6,8 +6,15 @@ import type { Coding } from "../../hl7-fhir-r4-core/Coding"; import type { Extension } from "../../hl7-fhir-r4-core/Extension"; export type USCoreRaceExtension_Extension_OmbCategorySliceFlat = Omit & Coding; +export type USCoreRaceExtension_Extension_OmbCategorySliceFlatAll = USCoreRaceExtension_Extension_OmbCategorySliceFlat; + export type USCoreRaceExtension_Extension_DetailedSliceFlat = Omit & Coding; +export type USCoreRaceExtension_Extension_DetailedSliceFlatAll = USCoreRaceExtension_Extension_DetailedSliceFlat; + export type USCoreRaceExtension_Extension_TextSliceFlat = Omit; +export type USCoreRaceExtension_Extension_TextSliceFlatAll = USCoreRaceExtension_Extension_TextSliceFlat & { + readonly url: "text"; +} import { isRawExtensionInput, @@ -16,7 +23,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, wrapSliceChoice, unwrapSliceChoice, isExtension, @@ -203,37 +209,37 @@ export class USCoreRaceExtensionProfile { return this } - public getExtensionOmbCategory(mode: 'flat'): USCoreRaceExtension_Extension_OmbCategorySliceFlat | undefined; + public getExtensionOmbCategory(mode: 'flat'): USCoreRaceExtension_Extension_OmbCategorySliceFlatAll | undefined; public getExtensionOmbCategory(mode: 'raw'): Extension | undefined; - public getExtensionOmbCategory(): USCoreRaceExtension_Extension_OmbCategorySliceFlat | undefined; - public getExtensionOmbCategory (mode: 'flat' | 'raw' = 'flat'): USCoreRaceExtension_Extension_OmbCategorySliceFlat | Extension | undefined { + public getExtensionOmbCategory(): USCoreRaceExtension_Extension_OmbCategorySliceFlatAll | undefined; + public getExtensionOmbCategory (mode: 'flat' | 'raw' = 'flat'): USCoreRaceExtension_Extension_OmbCategorySliceFlatAll | Extension | undefined { const match = USCoreRaceExtensionProfile.ombCategorySliceMatch const item = getArraySlice(this.resource.extension, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["url"], "valueCoding") + return unwrapSliceChoice(item, ["url"], "valueCoding") } - public getExtensionDetailed(mode: 'flat'): USCoreRaceExtension_Extension_DetailedSliceFlat | undefined; + public getExtensionDetailed(mode: 'flat'): USCoreRaceExtension_Extension_DetailedSliceFlatAll | undefined; public getExtensionDetailed(mode: 'raw'): Extension | undefined; - public getExtensionDetailed(): USCoreRaceExtension_Extension_DetailedSliceFlat | undefined; - public getExtensionDetailed (mode: 'flat' | 'raw' = 'flat'): USCoreRaceExtension_Extension_DetailedSliceFlat | Extension | undefined { + public getExtensionDetailed(): USCoreRaceExtension_Extension_DetailedSliceFlatAll | undefined; + public getExtensionDetailed (mode: 'flat' | 'raw' = 'flat'): USCoreRaceExtension_Extension_DetailedSliceFlatAll | Extension | undefined { const match = USCoreRaceExtensionProfile.detailedSliceMatch const item = getArraySlice(this.resource.extension, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["url"], "valueCoding") + return unwrapSliceChoice(item, ["url"], "valueCoding") } - public getExtensionText(mode: 'flat'): USCoreRaceExtension_Extension_TextSliceFlat | undefined; + public getExtensionText(mode: 'flat'): USCoreRaceExtension_Extension_TextSliceFlatAll | undefined; public getExtensionText(mode: 'raw'): Extension | undefined; - public getExtensionText(): USCoreRaceExtension_Extension_TextSliceFlat | undefined; - public getExtensionText (mode: 'flat' | 'raw' = 'flat'): USCoreRaceExtension_Extension_TextSliceFlat | Extension | undefined { + public getExtensionText(): USCoreRaceExtension_Extension_TextSliceFlatAll | undefined; + public getExtensionText (mode: 'flat' | 'raw' = 'flat'): USCoreRaceExtension_Extension_TextSliceFlatAll | Extension | undefined { const match = USCoreRaceExtensionProfile.textSliceMatch const item = getArraySlice(this.resource.extension, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["url"]) + return item as unknown as USCoreRaceExtension_Extension_TextSliceFlatAll } // Validation diff --git a/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Extension_USCoreTribalAffiliationExtension.ts b/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Extension_USCoreTribalAffiliationExtension.ts index a6632772..ceda1a02 100644 --- a/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Extension_USCoreTribalAffiliationExtension.ts +++ b/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Extension_USCoreTribalAffiliationExtension.ts @@ -6,7 +6,12 @@ import type { CodeableConcept } from "../../hl7-fhir-r4-core/CodeableConcept"; import type { Extension } from "../../hl7-fhir-r4-core/Extension"; export type USCoreTribalAffiliationExtension_Extension_TribalAffiliationSliceFlat = Omit & CodeableConcept; +export type USCoreTribalAffiliationExtension_Extension_TribalAffiliationSliceFlatAll = USCoreTribalAffiliationExtension_Extension_TribalAffiliationSliceFlat; + export type USCoreTribalAffiliationExtension_Extension_IsEnrolledSliceFlat = Omit; +export type USCoreTribalAffiliationExtension_Extension_IsEnrolledSliceFlatAll = USCoreTribalAffiliationExtension_Extension_IsEnrolledSliceFlat & { + readonly url: "isEnrolled"; +} import { isRawExtensionInput, @@ -15,7 +20,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, wrapSliceChoice, unwrapSliceChoice, isExtension, @@ -169,26 +173,26 @@ export class USCoreTribalAffiliationExtensionProfile { return this } - public getExtensionTribalAffiliation(mode: 'flat'): USCoreTribalAffiliationExtension_Extension_TribalAffiliationSliceFlat | undefined; + public getExtensionTribalAffiliation(mode: 'flat'): USCoreTribalAffiliationExtension_Extension_TribalAffiliationSliceFlatAll | undefined; public getExtensionTribalAffiliation(mode: 'raw'): Extension | undefined; - public getExtensionTribalAffiliation(): USCoreTribalAffiliationExtension_Extension_TribalAffiliationSliceFlat | undefined; - public getExtensionTribalAffiliation (mode: 'flat' | 'raw' = 'flat'): USCoreTribalAffiliationExtension_Extension_TribalAffiliationSliceFlat | Extension | undefined { + public getExtensionTribalAffiliation(): USCoreTribalAffiliationExtension_Extension_TribalAffiliationSliceFlatAll | undefined; + public getExtensionTribalAffiliation (mode: 'flat' | 'raw' = 'flat'): USCoreTribalAffiliationExtension_Extension_TribalAffiliationSliceFlatAll | Extension | undefined { const match = USCoreTribalAffiliationExtensionProfile.tribalAffiliationSliceMatch const item = getArraySlice(this.resource.extension, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["url"], "valueCodeableConcept") + return unwrapSliceChoice(item, ["url"], "valueCodeableConcept") } - public getExtensionIsEnrolled(mode: 'flat'): USCoreTribalAffiliationExtension_Extension_IsEnrolledSliceFlat | undefined; + public getExtensionIsEnrolled(mode: 'flat'): USCoreTribalAffiliationExtension_Extension_IsEnrolledSliceFlatAll | undefined; public getExtensionIsEnrolled(mode: 'raw'): Extension | undefined; - public getExtensionIsEnrolled(): USCoreTribalAffiliationExtension_Extension_IsEnrolledSliceFlat | undefined; - public getExtensionIsEnrolled (mode: 'flat' | 'raw' = 'flat'): USCoreTribalAffiliationExtension_Extension_IsEnrolledSliceFlat | Extension | undefined { + public getExtensionIsEnrolled(): USCoreTribalAffiliationExtension_Extension_IsEnrolledSliceFlatAll | undefined; + public getExtensionIsEnrolled (mode: 'flat' | 'raw' = 'flat'): USCoreTribalAffiliationExtension_Extension_IsEnrolledSliceFlatAll | Extension | undefined { const match = USCoreTribalAffiliationExtensionProfile.isEnrolledSliceMatch const item = getArraySlice(this.resource.extension, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["url"]) + return item as unknown as USCoreTribalAffiliationExtension_Extension_IsEnrolledSliceFlatAll } // Validation diff --git a/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreBloodPressureProfile.ts b/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreBloodPressureProfile.ts index d560fa53..e3bf5938 100644 --- a/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreBloodPressureProfile.ts +++ b/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreBloodPressureProfile.ts @@ -12,8 +12,15 @@ import type { Reference } from "../../hl7-fhir-r4-core/Reference"; import type { SampledData } from "../../hl7-fhir-r4-core/SampledData"; export type USCoreBloodPressureProfile_Category_VSCatSliceFlat = Omit; +export type USCoreBloodPressureProfile_Category_VSCatSliceFlatAll = USCoreBloodPressureProfile_Category_VSCatSliceFlat & { + readonly coding: [{ code: "vital-signs"; system: "http://terminology.hl7.org/CodeSystem/observation-category" }]; +} + export type USCoreBloodPressureProfile_Component_SystolicSliceFlat = Omit & Quantity; +export type USCoreBloodPressureProfile_Component_SystolicSliceFlatAll = USCoreBloodPressureProfile_Component_SystolicSliceFlat; + export type USCoreBloodPressureProfile_Component_DiastolicSliceFlat = Omit & Quantity; +export type USCoreBloodPressureProfile_Component_DiastolicSliceFlatAll = USCoreBloodPressureProfile_Component_DiastolicSliceFlat; import { ensureProfile, @@ -22,7 +29,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, wrapSliceChoice, unwrapSliceChoice, validateRequired, @@ -46,9 +52,15 @@ export type USCoreBloodPressureProfileRaw = { export class USCoreBloodPressureProfile { static readonly canonicalUrl = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-blood-pressure"; - private static readonly VSCatSliceMatch: Record = {"coding":[{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}]}; - private static readonly systolicSliceMatch: Record = {"code":{"coding":[{"system":"http://loinc.org","code":"8480-6"}]}}; - private static readonly diastolicSliceMatch: Record = {"code":{"coding":[{"system":"http://loinc.org","code":"8462-4"}]}}; + private static readonly VSCatSliceMatch: Record = { + "coding": [{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}], + } + private static readonly systolicSliceMatch: Record = { + "code": {"coding":[{"system":"http://loinc.org","code":"8480-6"}]}, + } + private static readonly diastolicSliceMatch: Record = { + "code": {"coding":[{"system":"http://loinc.org","code":"8462-4"}]}, + } private resource: Observation; @@ -310,37 +322,37 @@ export class USCoreBloodPressureProfile { return this } - public getVSCat(mode: 'flat'): USCoreBloodPressureProfile_Category_VSCatSliceFlat | undefined; + public getVSCat(mode: 'flat'): USCoreBloodPressureProfile_Category_VSCatSliceFlatAll | undefined; public getVSCat(mode: 'raw'): CodeableConcept | undefined; - public getVSCat(): USCoreBloodPressureProfile_Category_VSCatSliceFlat | undefined; - public getVSCat (mode: 'flat' | 'raw' = 'flat'): USCoreBloodPressureProfile_Category_VSCatSliceFlat | CodeableConcept | undefined { + public getVSCat(): USCoreBloodPressureProfile_Category_VSCatSliceFlatAll | undefined; + public getVSCat (mode: 'flat' | 'raw' = 'flat'): USCoreBloodPressureProfile_Category_VSCatSliceFlatAll | CodeableConcept | undefined { const match = USCoreBloodPressureProfile.VSCatSliceMatch const item = getArraySlice(this.resource.category, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["coding"]) + return item as unknown as USCoreBloodPressureProfile_Category_VSCatSliceFlatAll } - public getSystolic(mode: 'flat'): USCoreBloodPressureProfile_Component_SystolicSliceFlat | undefined; + public getSystolic(mode: 'flat'): USCoreBloodPressureProfile_Component_SystolicSliceFlatAll | undefined; public getSystolic(mode: 'raw'): ObservationComponent | undefined; - public getSystolic(): USCoreBloodPressureProfile_Component_SystolicSliceFlat | undefined; - public getSystolic (mode: 'flat' | 'raw' = 'flat'): USCoreBloodPressureProfile_Component_SystolicSliceFlat | ObservationComponent | undefined { + public getSystolic(): USCoreBloodPressureProfile_Component_SystolicSliceFlatAll | undefined; + public getSystolic (mode: 'flat' | 'raw' = 'flat'): USCoreBloodPressureProfile_Component_SystolicSliceFlatAll | ObservationComponent | undefined { const match = USCoreBloodPressureProfile.systolicSliceMatch const item = getArraySlice(this.resource.component, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["code"], "valueQuantity") + return unwrapSliceChoice(item, ["code"], "valueQuantity") } - public getDiastolic(mode: 'flat'): USCoreBloodPressureProfile_Component_DiastolicSliceFlat | undefined; + public getDiastolic(mode: 'flat'): USCoreBloodPressureProfile_Component_DiastolicSliceFlatAll | undefined; public getDiastolic(mode: 'raw'): ObservationComponent | undefined; - public getDiastolic(): USCoreBloodPressureProfile_Component_DiastolicSliceFlat | undefined; - public getDiastolic (mode: 'flat' | 'raw' = 'flat'): USCoreBloodPressureProfile_Component_DiastolicSliceFlat | ObservationComponent | undefined { + public getDiastolic(): USCoreBloodPressureProfile_Component_DiastolicSliceFlatAll | undefined; + public getDiastolic (mode: 'flat' | 'raw' = 'flat'): USCoreBloodPressureProfile_Component_DiastolicSliceFlatAll | ObservationComponent | undefined { const match = USCoreBloodPressureProfile.diastolicSliceMatch const item = getArraySlice(this.resource.component, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["code"], "valueQuantity") + return unwrapSliceChoice(item, ["code"], "valueQuantity") } // Validation diff --git a/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreBodyWeightProfile.ts b/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreBodyWeightProfile.ts index 9284e2b0..86ad76a4 100644 --- a/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreBodyWeightProfile.ts +++ b/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreBodyWeightProfile.ts @@ -12,6 +12,9 @@ import type { Reference } from "../../hl7-fhir-r4-core/Reference"; import type { SampledData } from "../../hl7-fhir-r4-core/SampledData"; export type USCoreBodyWeightProfile_Category_VSCatSliceFlat = Omit; +export type USCoreBodyWeightProfile_Category_VSCatSliceFlatAll = USCoreBodyWeightProfile_Category_VSCatSliceFlat & { + readonly coding: [{ code: "vital-signs"; system: "http://terminology.hl7.org/CodeSystem/observation-category" }]; +} import { ensureProfile, @@ -20,7 +23,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, validateRequired, validateExcluded, validateFixedValue, @@ -41,7 +43,9 @@ export type USCoreBodyWeightProfileRaw = { export class USCoreBodyWeightProfile { static readonly canonicalUrl = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-body-weight"; - private static readonly VSCatSliceMatch: Record = {"coding":[{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}]}; + private static readonly VSCatSliceMatch: Record = { + "coding": [{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}], + } private resource: Observation; @@ -259,15 +263,15 @@ export class USCoreBodyWeightProfile { return this } - public getVSCat(mode: 'flat'): USCoreBodyWeightProfile_Category_VSCatSliceFlat | undefined; + public getVSCat(mode: 'flat'): USCoreBodyWeightProfile_Category_VSCatSliceFlatAll | undefined; public getVSCat(mode: 'raw'): CodeableConcept | undefined; - public getVSCat(): USCoreBodyWeightProfile_Category_VSCatSliceFlat | undefined; - public getVSCat (mode: 'flat' | 'raw' = 'flat'): USCoreBodyWeightProfile_Category_VSCatSliceFlat | CodeableConcept | undefined { + public getVSCat(): USCoreBodyWeightProfile_Category_VSCatSliceFlatAll | undefined; + public getVSCat (mode: 'flat' | 'raw' = 'flat'): USCoreBodyWeightProfile_Category_VSCatSliceFlatAll | CodeableConcept | undefined { const match = USCoreBodyWeightProfile.VSCatSliceMatch const item = getArraySlice(this.resource.category, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["coding"]) + return item as unknown as USCoreBodyWeightProfile_Category_VSCatSliceFlatAll } // Validation diff --git a/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreVitalSignsProfile.ts b/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreVitalSignsProfile.ts index a63b70c9..e1c90666 100644 --- a/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreVitalSignsProfile.ts +++ b/examples/typescript-us-core/fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreVitalSignsProfile.ts @@ -12,6 +12,9 @@ import type { Reference } from "../../hl7-fhir-r4-core/Reference"; import type { SampledData } from "../../hl7-fhir-r4-core/SampledData"; export type USCoreVitalSignsProfile_Category_VSCatSliceFlat = Omit; +export type USCoreVitalSignsProfile_Category_VSCatSliceFlatAll = USCoreVitalSignsProfile_Category_VSCatSliceFlat & { + readonly coding: [{ code: "vital-signs"; system: "http://terminology.hl7.org/CodeSystem/observation-category" }]; +} import { ensureProfile, @@ -20,7 +23,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, validateRequired, validateExcluded, validateFixedValue, @@ -42,7 +44,9 @@ export type USCoreVitalSignsProfileRaw = { export class USCoreVitalSignsProfile { static readonly canonicalUrl = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-vital-signs"; - private static readonly VSCatSliceMatch: Record = {"coding":[{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}]}; + private static readonly VSCatSliceMatch: Record = { + "coding": [{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}], + } private resource: Observation; @@ -262,15 +266,15 @@ export class USCoreVitalSignsProfile { return this } - public getVSCat(mode: 'flat'): USCoreVitalSignsProfile_Category_VSCatSliceFlat | undefined; + public getVSCat(mode: 'flat'): USCoreVitalSignsProfile_Category_VSCatSliceFlatAll | undefined; public getVSCat(mode: 'raw'): CodeableConcept | undefined; - public getVSCat(): USCoreVitalSignsProfile_Category_VSCatSliceFlat | undefined; - public getVSCat (mode: 'flat' | 'raw' = 'flat'): USCoreVitalSignsProfile_Category_VSCatSliceFlat | CodeableConcept | undefined { + public getVSCat(): USCoreVitalSignsProfile_Category_VSCatSliceFlatAll | undefined; + public getVSCat (mode: 'flat' | 'raw' = 'flat'): USCoreVitalSignsProfile_Category_VSCatSliceFlatAll | CodeableConcept | undefined { const match = USCoreVitalSignsProfile.VSCatSliceMatch const item = getArraySlice(this.resource.category, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["coding"]) + return item as unknown as USCoreVitalSignsProfile_Category_VSCatSliceFlatAll } // Validation diff --git a/examples/typescript-us-core/profile-bodyweight.test.ts b/examples/typescript-us-core/profile-bodyweight.test.ts index 65359e0c..886c5eeb 100644 --- a/examples/typescript-us-core/profile-bodyweight.test.ts +++ b/examples/typescript-us-core/profile-bodyweight.test.ts @@ -5,6 +5,10 @@ import { describe, expect, test } from "bun:test"; import type { Observation } from "./fhir-types/hl7-fhir-r4-core/Observation"; import { USCoreBodyWeightProfile } from "./fhir-types/hl7-fhir-us-core/profiles"; +import type { + USCoreBodyWeightProfile_Category_VSCatSliceFlat as VSCatFlat, + USCoreBodyWeightProfile_Category_VSCatSliceFlatAll as VSCatFlatAll, +} from "./fhir-types/hl7-fhir-us-core/profiles/Observation_USCoreBodyWeightProfile"; describe("demo: create a US Core body weight observation", () => { test("build a valid body weight resource step by step", () => { @@ -95,12 +99,31 @@ describe("demo: read a US Core body weight observation from JSON", () => { // Code is a fixed value — auto-set by the profile, read-only (no setter) expect(profile.getCode()!.coding![0]!.code).toBe("29463-7"); - // Slice accessor strips discriminator keys (coding) by default — only user data remains - expect(profile.getVSCat()).toEqual({ text: "Vital Signs" }); - // Use "raw" mode to see the full element including discriminator - expect(profile.getVSCat("raw")!.coding).toEqual([ - { code: "vital-signs", system: "http://terminology.hl7.org/CodeSystem/observation-category" }, - ]); + // Slice getter returns SliceFlat — includes both user data and discriminator values + expect(profile.getVSCat()).toEqual({ + text: "Vital Signs", + coding: [{ code: "vital-signs", system: "http://terminology.hl7.org/CodeSystem/observation-category" }], + }); + }); +}); + +describe("slice input/flat type split", () => { + test("setVSCat accepts SliceFlatInput, getVSCat returns SliceFlat", () => { + const profile = USCoreBodyWeightProfile.create({ + status: "final", + subject: { reference: "Patient/pt-1" }, + }); + + // Setter accepts SliceFlat — only user-supplied fields, no discriminators + const input: VSCatFlat = { text: "Vital Signs" }; + profile.setVSCat(input); + + // Getter returns SliceFlatAll — includes discriminator values + user data + const flat: VSCatFlatAll = profile.getVSCat()!; + expect(flat).toEqual({ + text: "Vital Signs", + coding: [{ code: "vital-signs", system: "http://terminology.hl7.org/CodeSystem/observation-category" }], + }); }); }); diff --git a/examples/typescript-us-core/profile-bp.test.ts b/examples/typescript-us-core/profile-bp.test.ts index a2aa5760..a973313d 100644 --- a/examples/typescript-us-core/profile-bp.test.ts +++ b/examples/typescript-us-core/profile-bp.test.ts @@ -109,8 +109,8 @@ describe("demo: read a US Core blood pressure observation from JSON", () => { expect(profile.getSystolic("raw")!.valueQuantity!.value).toBe(120); expect(profile.getSystolic("raw")!.code?.coding?.[0]?.code).toBe("8480-6"); - // Category slice — flat strips discriminator, raw includes it - expect(profile.getVSCat()).toEqual({ text: "Vital Signs" }); + // Category slice — flat returns SliceFlat type, raw includes full element + expect(profile.getVSCat()!.text).toBe("Vital Signs"); expect(profile.getVSCat("raw")!.coding).toEqual([ { code: "vital-signs", system: "http://terminology.hl7.org/CodeSystem/observation-category" }, ]); diff --git a/src/api/writer-generator/typescript/name.ts b/src/api/writer-generator/typescript/name.ts index 6eacb528..f6bcedca 100644 --- a/src/api/writer-generator/typescript/name.ts +++ b/src/api/writer-generator/typescript/name.ts @@ -96,6 +96,10 @@ export const tsSliceFlatTypeName = (profileName: string, fieldName: string, slic return `${uppercaseFirstLetter(profileName)}_${uppercaseFirstLetter(normalizeTsName(fieldName))}_${uppercaseFirstLetter(normalizeTsName(sliceName))}SliceFlat`; }; +export const tsSliceFlatAllTypeName = (profileName: string, fieldName: string, sliceName: string): string => { + return `${uppercaseFirstLetter(profileName)}_${uppercaseFirstLetter(normalizeTsName(fieldName))}_${uppercaseFirstLetter(normalizeTsName(sliceName))}SliceFlatAll`; +}; + export const tsExtensionFlatTypeName = (profileName: string, extensionName: string): string => { return `${uppercaseFirstLetter(profileName)}_${uppercaseFirstLetter(normalizeTsName(extensionName))}Flat`; }; diff --git a/src/api/writer-generator/typescript/profile-slices.ts b/src/api/writer-generator/typescript/profile-slices.ts index 6675e6e1..a56ec722 100644 --- a/src/api/writer-generator/typescript/profile-slices.ts +++ b/src/api/writer-generator/typescript/profile-slices.ts @@ -13,6 +13,7 @@ import { tsProfileClassName, tsResolvedSliceBaseName, tsResourceName, + tsSliceFlatAllTypeName, tsSliceFlatTypeName, tsSliceStaticName, } from "./name"; @@ -159,14 +160,14 @@ export const generateSliceSetters = ( for (const sliceDef of sliceDefs) { const baseName = tsResolvedSliceBaseName(sliceBaseNames, sliceDef.fieldName, sliceDef.sliceName); const methodName = `set${baseName}`; - const typeName = tsSliceFlatTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName); + const inputTypeName = tsSliceFlatTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName); const matchRef = `${profileClassName}.${tsSliceStaticName(sliceDef.sliceName)}SliceMatch`; const tsField = tsFieldName(sliceDef.fieldName); const fieldAccess = tsGet("this.resource", tsField); const baseType = sliceDef.typedBaseType; // Make input optional when there are no required fields (input can be empty object) const inputOptional = sliceDef.required.length === 0; - const unionType = `${typeName} | ${baseType}`; + const unionType = `${inputTypeName} | ${baseType}`; const paramSignature = inputOptional ? `(input?: ${unionType}): this` : `(input: ${unionType}): this`; w.curlyBlock(["public", methodName, paramSignature], () => { w.line(`const match = ${matchRef}`); @@ -209,16 +210,16 @@ export const generateSliceGetters = ( for (const sliceDef of sliceDefs) { const baseName = tsResolvedSliceBaseName(sliceBaseNames, sliceDef.fieldName, sliceDef.sliceName); const getMethodName = `get${baseName}`; - const typeName = tsSliceFlatTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName); + const flatTypeName = tsSliceFlatAllTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName); const matchRef = `${profileClassName}.${tsSliceStaticName(sliceDef.sliceName)}SliceMatch`; const matchKeys = JSON.stringify(Object.keys(sliceDef.match)); const tsField = tsFieldName(sliceDef.fieldName); const fieldAccess = tsGet("this.resource", tsField); const baseType = sliceDef.typedBaseType; - const defaultReturn = defaultMode === "raw" ? baseType : typeName; + const defaultReturn = defaultMode === "raw" ? baseType : flatTypeName; // Overload signatures - w.lineSM(`public ${getMethodName}(mode: 'flat'): ${typeName} | undefined`); + w.lineSM(`public ${getMethodName}(mode: 'flat'): ${flatTypeName} | undefined`); w.lineSM(`public ${getMethodName}(mode: 'raw'): ${baseType} | undefined`); w.lineSM(`public ${getMethodName}(): ${defaultReturn} | undefined`); @@ -227,7 +228,7 @@ export const generateSliceGetters = ( [ "public", getMethodName, - `(mode: 'flat' | 'raw' = '${defaultMode}'): ${typeName} | ${baseType} | undefined`, + `(mode: 'flat' | 'raw' = '${defaultMode}'): ${flatTypeName} | ${baseType} | undefined`, ], () => { w.line(`const match = ${matchRef}`); @@ -243,13 +244,13 @@ export const generateSliceGetters = ( } else { w.line("if (mode === 'raw') return item"); } - if (sliceDef.typeDiscriminator) { - w.line(`return item as ${typeName}`); - } else if (sliceDef.constrainedChoice) { + if (sliceDef.constrainedChoice) { const cc = sliceDef.constrainedChoice; - w.line(`return unwrapSliceChoice<${typeName}>(item, ${matchKeys}, ${JSON.stringify(cc.variant)})`); + w.line( + `return unwrapSliceChoice<${flatTypeName}>(item, ${matchKeys}, ${JSON.stringify(cc.variant)})`, + ); } else { - w.line(`return stripMatchKeys<${typeName}>(item, ${matchKeys})`); + w.line(`return item as unknown as ${flatTypeName}`); } }, ); diff --git a/src/api/writer-generator/typescript/profile.ts b/src/api/writer-generator/typescript/profile.ts index 0d4deac1..45b90da2 100644 --- a/src/api/writer-generator/typescript/profile.ts +++ b/src/api/writer-generator/typescript/profile.ts @@ -27,6 +27,7 @@ import { tsQualifiedExtensionMethodBaseName, tsQualifiedSliceMethodBaseName, tsResourceName, + tsSliceFlatAllTypeName, tsSliceFlatTypeName, tsSliceMethodBaseName, tsSliceStaticName, @@ -247,7 +248,6 @@ const generateProfileHelpersImport = ( imports.push("applySliceMatch", "matchesValue", "setArraySlice", "getArraySlice", "ensureSliceDefaults"); if (extensions.some((ext) => ext.path.split(".").some((s) => s !== "extension"))) imports.push("ensurePath"); if (extensions.some((ext) => ext.isComplex && ext.subExtensions)) imports.push("extractComplexExtension"); - if (sliceDefs.some((s) => !s.typeDiscriminator)) imports.push("stripMatchKeys"); if (sliceDefs.some((s) => s.constrainedChoice)) imports.push("wrapSliceChoice", "unwrapSliceChoice"); if (extensions.some((ext) => ext.url)) { imports.push("isExtension", "getExtensionValue", "pushExtension"); @@ -343,7 +343,17 @@ export const generateProfileImports = (w: TypeScript, tsIndex: TypeSchemaIndex, const generateStaticSliceFields = (w: TypeScript, sliceDefs: SliceDef[]) => { for (const sliceDef of sliceDefs) { const staticName = `${tsSliceStaticName(sliceDef.sliceName)}SliceMatch`; - w.lineSM(`private static readonly ${staticName}: Record = ${JSON.stringify(sliceDef.match)}`); + const json = JSON.stringify(sliceDef.match); + const prefix = `private static readonly ${staticName}: Record = `; + if (prefix.length + json.length <= (w.opts.lineWidth ?? 120)) { + w.lineSM(`${prefix}${json}`); + } else { + w.curlyBlock([prefix.trimEnd()], () => { + for (const [key, value] of Object.entries(sliceDef.match)) { + w.line(`${JSON.stringify(key)}: ${JSON.stringify(value)},`); + } + }); + } } if (sliceDefs.length > 0) w.line(); }; @@ -607,11 +617,27 @@ const generateInlineExtensionInputTypes = (w: TypeScript, tsIndex: TypeSchemaInd } }; +/** Convert a JS value to a TypeScript type literal string (e.g. `{ code: "vital-signs"; system: "http://..." }`). */ +const valueToTypeLiteral = (value: unknown): string => { + if (value === null || value === undefined) return "undefined"; + if (typeof value === "string") return JSON.stringify(value); + if (typeof value === "number" || typeof value === "boolean") return String(value); + if (Array.isArray(value)) return `[${value.map(valueToTypeLiteral).join(", ")}]`; + if (typeof value === "object") { + const entries = Object.entries(value as Record) + .map(([k, v]) => `${k}: ${valueToTypeLiteral(v)}`) + .join("; "); + return `{ ${entries} }`; + } + return "unknown"; +}; + const generateSliceInputTypes = (w: TypeScript, flatProfile: ProfileTypeSchema, sliceDefs: SliceDef[]) => { if (sliceDefs.length === 0) return; const tsProfileName = tsResourceName(flatProfile.identifier); for (const sliceDef of sliceDefs) { - const typeName = tsSliceFlatTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName); + const inputTypeName = tsSliceFlatTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName); + const flatTypeName = tsSliceFlatAllTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName); const matchFields = sliceDef.typeDiscriminator ? [] : Object.keys(sliceDef.match); const allExcluded = [...new Set([...sliceDef.excluded, ...matchFields])]; if (sliceDef.constrainedChoice) { @@ -624,19 +650,39 @@ const generateSliceInputTypes = (w: TypeScript, flatProfile: ProfileTypeSchema, const excludedNames = allExcluded.map((name) => JSON.stringify(name)); const requiredNames = sliceDef.required.map((name) => JSON.stringify(name)); const baseType = sliceDef.typedBaseType; - let typeExpr = baseType; + let inputTypeExpr = baseType; if (excludedNames.length > 0) { - typeExpr = `Omit<${typeExpr}, ${excludedNames.join(" | ")}>`; + inputTypeExpr = `Omit<${inputTypeExpr}, ${excludedNames.join(" | ")}>`; } if (requiredNames.length > 0) { - typeExpr = `${typeExpr} & Required>`; + inputTypeExpr = `${inputTypeExpr} & Required>`; } if (sliceDef.constrainedChoice) { - typeExpr = `${typeExpr} & ${tsTypeFromIdentifier(sliceDef.constrainedChoice.variantType)}`; + inputTypeExpr = `${inputTypeExpr} & ${tsTypeFromIdentifier(sliceDef.constrainedChoice.variantType)}`; } - w.lineSM(`export type ${typeName} = ${typeExpr}`); + // Input type — setter parameter, no discriminator fields + w.lineSM(`export type ${inputTypeName} = ${inputTypeExpr}`); + // Flat type — getter return, includes readonly discriminator values as literal types + const safeMatchEntries = + matchFields.length > 0 && !sliceDef.constrainedChoice + ? matchFields + .filter((key) => { + const v = sliceDef.match[key]; + return Array.isArray(v) || typeof v !== "object" || v === null; + }) + .map((key) => ({ key, typeLiteral: valueToTypeLiteral(sliceDef.match[key]) })) + : []; + if (safeMatchEntries.length > 0) { + w.curlyBlock([`export type ${flatTypeName} = ${inputTypeName} &`], () => { + for (const entry of safeMatchEntries) { + w.lineSM(`readonly ${entry.key}: ${entry.typeLiteral}`); + } + }); + } else { + w.lineSM(`export type ${flatTypeName} = ${inputTypeName}`); + } + w.line(); } - w.line(); }; const generateRawType = (w: TypeScript, flatProfile: ProfileTypeSchema, factoryInfo: ProfileFactoryInfo) => { diff --git a/test/api/write-generator/__snapshots__/typescript.test.ts.snap b/test/api/write-generator/__snapshots__/typescript.test.ts.snap index 616bd22e..27eed4b5 100644 --- a/test/api/write-generator/__snapshots__/typescript.test.ts.snap +++ b/test/api/write-generator/__snapshots__/typescript.test.ts.snap @@ -323,6 +323,9 @@ import type { Quantity } from "../../hl7-fhir-r4-core/Quantity"; import type { Reference } from "../../hl7-fhir-r4-core/Reference"; export type Observation_bodyweight_Category_VSCatSliceFlat = Omit; +export type Observation_bodyweight_Category_VSCatSliceFlatAll = Observation_bodyweight_Category_VSCatSliceFlat & { + readonly coding: [{ code: "vital-signs"; system: "http://terminology.hl7.org/CodeSystem/observation-category" }]; +} import { ensureProfile, @@ -331,7 +334,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, validateRequired, validateExcluded, validateFixedValue, @@ -352,7 +354,9 @@ export type observation_bodyweightProfileRaw = { export class observation_bodyweightProfile { static readonly canonicalUrl = "http://hl7.org/fhir/StructureDefinition/bodyweight"; - private static readonly VSCatSliceMatch: Record = {"coding":[{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}]}; + private static readonly VSCatSliceMatch: Record = { + "coding": [{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}], + } private resource: Observation; @@ -480,15 +484,15 @@ export class observation_bodyweightProfile { return this } - public getVSCat(mode: 'flat'): Observation_bodyweight_Category_VSCatSliceFlat | undefined; + public getVSCat(mode: 'flat'): Observation_bodyweight_Category_VSCatSliceFlatAll | undefined; public getVSCat(mode: 'raw'): CodeableConcept | undefined; - public getVSCat(): Observation_bodyweight_Category_VSCatSliceFlat | undefined; - public getVSCat (mode: 'flat' | 'raw' = 'flat'): Observation_bodyweight_Category_VSCatSliceFlat | CodeableConcept | undefined { + public getVSCat(): Observation_bodyweight_Category_VSCatSliceFlatAll | undefined; + public getVSCat (mode: 'flat' | 'raw' = 'flat'): Observation_bodyweight_Category_VSCatSliceFlatAll | CodeableConcept | undefined { const match = observation_bodyweightProfile.VSCatSliceMatch const item = getArraySlice(this.resource.category, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["coding"]) + return item as unknown as Observation_bodyweight_Category_VSCatSliceFlatAll } // Validation @@ -535,8 +539,15 @@ import type { Quantity } from "../../hl7-fhir-r4-core/Quantity"; import type { Reference } from "../../hl7-fhir-r4-core/Reference"; export type Observation_bp_Category_VSCatSliceFlat = Omit; +export type Observation_bp_Category_VSCatSliceFlatAll = Observation_bp_Category_VSCatSliceFlat & { + readonly coding: [{ code: "vital-signs"; system: "http://terminology.hl7.org/CodeSystem/observation-category" }]; +} + export type Observation_bp_Component_SystolicBPSliceFlat = Omit & Quantity; +export type Observation_bp_Component_SystolicBPSliceFlatAll = Observation_bp_Component_SystolicBPSliceFlat; + export type Observation_bp_Component_DiastolicBPSliceFlat = Omit & Quantity; +export type Observation_bp_Component_DiastolicBPSliceFlatAll = Observation_bp_Component_DiastolicBPSliceFlat; import { ensureProfile, @@ -545,7 +556,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, wrapSliceChoice, unwrapSliceChoice, validateRequired, @@ -569,9 +579,15 @@ export type observation_bpProfileRaw = { export class observation_bpProfile { static readonly canonicalUrl = "http://hl7.org/fhir/StructureDefinition/bp"; - private static readonly VSCatSliceMatch: Record = {"coding":[{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}]}; - private static readonly SystolicBPSliceMatch: Record = {"code":{"coding":[{"code":"8480-6","system":"http://loinc.org"}]}}; - private static readonly DiastolicBPSliceMatch: Record = {"code":{"coding":[{"code":"8462-4","system":"http://loinc.org"}]}}; + private static readonly VSCatSliceMatch: Record = { + "coding": [{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}], + } + private static readonly SystolicBPSliceMatch: Record = { + "code": {"coding":[{"code":"8480-6","system":"http://loinc.org"}]}, + } + private static readonly DiastolicBPSliceMatch: Record = { + "code": {"coding":[{"code":"8462-4","system":"http://loinc.org"}]}, + } private resource: Observation; @@ -743,37 +759,37 @@ export class observation_bpProfile { return this } - public getVSCat(mode: 'flat'): Observation_bp_Category_VSCatSliceFlat | undefined; + public getVSCat(mode: 'flat'): Observation_bp_Category_VSCatSliceFlatAll | undefined; public getVSCat(mode: 'raw'): CodeableConcept | undefined; - public getVSCat(): Observation_bp_Category_VSCatSliceFlat | undefined; - public getVSCat (mode: 'flat' | 'raw' = 'flat'): Observation_bp_Category_VSCatSliceFlat | CodeableConcept | undefined { + public getVSCat(): Observation_bp_Category_VSCatSliceFlatAll | undefined; + public getVSCat (mode: 'flat' | 'raw' = 'flat'): Observation_bp_Category_VSCatSliceFlatAll | CodeableConcept | undefined { const match = observation_bpProfile.VSCatSliceMatch const item = getArraySlice(this.resource.category, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["coding"]) + return item as unknown as Observation_bp_Category_VSCatSliceFlatAll } - public getSystolicBP(mode: 'flat'): Observation_bp_Component_SystolicBPSliceFlat | undefined; + public getSystolicBP(mode: 'flat'): Observation_bp_Component_SystolicBPSliceFlatAll | undefined; public getSystolicBP(mode: 'raw'): ObservationComponent | undefined; - public getSystolicBP(): Observation_bp_Component_SystolicBPSliceFlat | undefined; - public getSystolicBP (mode: 'flat' | 'raw' = 'flat'): Observation_bp_Component_SystolicBPSliceFlat | ObservationComponent | undefined { + public getSystolicBP(): Observation_bp_Component_SystolicBPSliceFlatAll | undefined; + public getSystolicBP (mode: 'flat' | 'raw' = 'flat'): Observation_bp_Component_SystolicBPSliceFlatAll | ObservationComponent | undefined { const match = observation_bpProfile.SystolicBPSliceMatch const item = getArraySlice(this.resource.component, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["code"], "valueQuantity") + return unwrapSliceChoice(item, ["code"], "valueQuantity") } - public getDiastolicBP(mode: 'flat'): Observation_bp_Component_DiastolicBPSliceFlat | undefined; + public getDiastolicBP(mode: 'flat'): Observation_bp_Component_DiastolicBPSliceFlatAll | undefined; public getDiastolicBP(mode: 'raw'): ObservationComponent | undefined; - public getDiastolicBP(): Observation_bp_Component_DiastolicBPSliceFlat | undefined; - public getDiastolicBP (mode: 'flat' | 'raw' = 'flat'): Observation_bp_Component_DiastolicBPSliceFlat | ObservationComponent | undefined { + public getDiastolicBP(): Observation_bp_Component_DiastolicBPSliceFlatAll | undefined; + public getDiastolicBP (mode: 'flat' | 'raw' = 'flat'): Observation_bp_Component_DiastolicBPSliceFlatAll | ObservationComponent | undefined { const match = observation_bpProfile.DiastolicBPSliceMatch const item = getArraySlice(this.resource.component, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["code"], "valueQuantity") + return unwrapSliceChoice(item, ["code"], "valueQuantity") } // Validation @@ -1080,8 +1096,15 @@ import type { Reference } from "../../hl7-fhir-r4-core/Reference"; import type { SampledData } from "../../hl7-fhir-r4-core/SampledData"; export type USCoreBloodPressureProfile_Category_VSCatSliceFlat = Omit; +export type USCoreBloodPressureProfile_Category_VSCatSliceFlatAll = USCoreBloodPressureProfile_Category_VSCatSliceFlat & { + readonly coding: [{ code: "vital-signs"; system: "http://terminology.hl7.org/CodeSystem/observation-category" }]; +} + export type USCoreBloodPressureProfile_Component_SystolicSliceFlat = Omit & Quantity; +export type USCoreBloodPressureProfile_Component_SystolicSliceFlatAll = USCoreBloodPressureProfile_Component_SystolicSliceFlat; + export type USCoreBloodPressureProfile_Component_DiastolicSliceFlat = Omit & Quantity; +export type USCoreBloodPressureProfile_Component_DiastolicSliceFlatAll = USCoreBloodPressureProfile_Component_DiastolicSliceFlat; import { ensureProfile, @@ -1090,7 +1113,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, wrapSliceChoice, unwrapSliceChoice, validateRequired, @@ -1114,9 +1136,15 @@ export type USCoreBloodPressureProfileRaw = { export class USCoreBloodPressureProfile { static readonly canonicalUrl = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-blood-pressure"; - private static readonly VSCatSliceMatch: Record = {"coding":[{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}]}; - private static readonly systolicSliceMatch: Record = {"code":{"coding":[{"system":"http://loinc.org","code":"8480-6"}]}}; - private static readonly diastolicSliceMatch: Record = {"code":{"coding":[{"system":"http://loinc.org","code":"8462-4"}]}}; + private static readonly VSCatSliceMatch: Record = { + "coding": [{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}], + } + private static readonly systolicSliceMatch: Record = { + "code": {"coding":[{"system":"http://loinc.org","code":"8480-6"}]}, + } + private static readonly diastolicSliceMatch: Record = { + "code": {"coding":[{"system":"http://loinc.org","code":"8462-4"}]}, + } private resource: Observation; @@ -1378,37 +1406,37 @@ export class USCoreBloodPressureProfile { return this } - public getVSCat(mode: 'flat'): USCoreBloodPressureProfile_Category_VSCatSliceFlat | undefined; + public getVSCat(mode: 'flat'): USCoreBloodPressureProfile_Category_VSCatSliceFlatAll | undefined; public getVSCat(mode: 'raw'): CodeableConcept | undefined; - public getVSCat(): USCoreBloodPressureProfile_Category_VSCatSliceFlat | undefined; - public getVSCat (mode: 'flat' | 'raw' = 'flat'): USCoreBloodPressureProfile_Category_VSCatSliceFlat | CodeableConcept | undefined { + public getVSCat(): USCoreBloodPressureProfile_Category_VSCatSliceFlatAll | undefined; + public getVSCat (mode: 'flat' | 'raw' = 'flat'): USCoreBloodPressureProfile_Category_VSCatSliceFlatAll | CodeableConcept | undefined { const match = USCoreBloodPressureProfile.VSCatSliceMatch const item = getArraySlice(this.resource.category, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["coding"]) + return item as unknown as USCoreBloodPressureProfile_Category_VSCatSliceFlatAll } - public getSystolic(mode: 'flat'): USCoreBloodPressureProfile_Component_SystolicSliceFlat | undefined; + public getSystolic(mode: 'flat'): USCoreBloodPressureProfile_Component_SystolicSliceFlatAll | undefined; public getSystolic(mode: 'raw'): ObservationComponent | undefined; - public getSystolic(): USCoreBloodPressureProfile_Component_SystolicSliceFlat | undefined; - public getSystolic (mode: 'flat' | 'raw' = 'flat'): USCoreBloodPressureProfile_Component_SystolicSliceFlat | ObservationComponent | undefined { + public getSystolic(): USCoreBloodPressureProfile_Component_SystolicSliceFlatAll | undefined; + public getSystolic (mode: 'flat' | 'raw' = 'flat'): USCoreBloodPressureProfile_Component_SystolicSliceFlatAll | ObservationComponent | undefined { const match = USCoreBloodPressureProfile.systolicSliceMatch const item = getArraySlice(this.resource.component, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["code"], "valueQuantity") + return unwrapSliceChoice(item, ["code"], "valueQuantity") } - public getDiastolic(mode: 'flat'): USCoreBloodPressureProfile_Component_DiastolicSliceFlat | undefined; + public getDiastolic(mode: 'flat'): USCoreBloodPressureProfile_Component_DiastolicSliceFlatAll | undefined; public getDiastolic(mode: 'raw'): ObservationComponent | undefined; - public getDiastolic(): USCoreBloodPressureProfile_Component_DiastolicSliceFlat | undefined; - public getDiastolic (mode: 'flat' | 'raw' = 'flat'): USCoreBloodPressureProfile_Component_DiastolicSliceFlat | ObservationComponent | undefined { + public getDiastolic(): USCoreBloodPressureProfile_Component_DiastolicSliceFlatAll | undefined; + public getDiastolic (mode: 'flat' | 'raw' = 'flat'): USCoreBloodPressureProfile_Component_DiastolicSliceFlatAll | ObservationComponent | undefined { const match = USCoreBloodPressureProfile.diastolicSliceMatch const item = getArraySlice(this.resource.component, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["code"], "valueQuantity") + return unwrapSliceChoice(item, ["code"], "valueQuantity") } // Validation @@ -1462,6 +1490,9 @@ import type { Reference } from "../../hl7-fhir-r4-core/Reference"; import type { SampledData } from "../../hl7-fhir-r4-core/SampledData"; export type USCoreBodyWeightProfile_Category_VSCatSliceFlat = Omit; +export type USCoreBodyWeightProfile_Category_VSCatSliceFlatAll = USCoreBodyWeightProfile_Category_VSCatSliceFlat & { + readonly coding: [{ code: "vital-signs"; system: "http://terminology.hl7.org/CodeSystem/observation-category" }]; +} import { ensureProfile, @@ -1470,7 +1501,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, validateRequired, validateExcluded, validateFixedValue, @@ -1491,7 +1521,9 @@ export type USCoreBodyWeightProfileRaw = { export class USCoreBodyWeightProfile { static readonly canonicalUrl = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-body-weight"; - private static readonly VSCatSliceMatch: Record = {"coding":[{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}]}; + private static readonly VSCatSliceMatch: Record = { + "coding": [{"code":"vital-signs","system":"http://terminology.hl7.org/CodeSystem/observation-category"}], + } private resource: Observation; @@ -1709,15 +1741,15 @@ export class USCoreBodyWeightProfile { return this } - public getVSCat(mode: 'flat'): USCoreBodyWeightProfile_Category_VSCatSliceFlat | undefined; + public getVSCat(mode: 'flat'): USCoreBodyWeightProfile_Category_VSCatSliceFlatAll | undefined; public getVSCat(mode: 'raw'): CodeableConcept | undefined; - public getVSCat(): USCoreBodyWeightProfile_Category_VSCatSliceFlat | undefined; - public getVSCat (mode: 'flat' | 'raw' = 'flat'): USCoreBodyWeightProfile_Category_VSCatSliceFlat | CodeableConcept | undefined { + public getVSCat(): USCoreBodyWeightProfile_Category_VSCatSliceFlatAll | undefined; + public getVSCat (mode: 'flat' | 'raw' = 'flat'): USCoreBodyWeightProfile_Category_VSCatSliceFlatAll | CodeableConcept | undefined { const match = USCoreBodyWeightProfile.VSCatSliceMatch const item = getArraySlice(this.resource.category, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["coding"]) + return item as unknown as USCoreBodyWeightProfile_Category_VSCatSliceFlatAll } // Validation @@ -1773,8 +1805,15 @@ import type { Coding } from "../../hl7-fhir-r4-core/Coding"; import type { Extension } from "../../hl7-fhir-r4-core/Extension"; export type USCoreRaceExtension_Extension_OmbCategorySliceFlat = Omit & Coding; +export type USCoreRaceExtension_Extension_OmbCategorySliceFlatAll = USCoreRaceExtension_Extension_OmbCategorySliceFlat; + export type USCoreRaceExtension_Extension_DetailedSliceFlat = Omit & Coding; +export type USCoreRaceExtension_Extension_DetailedSliceFlatAll = USCoreRaceExtension_Extension_DetailedSliceFlat; + export type USCoreRaceExtension_Extension_TextSliceFlat = Omit; +export type USCoreRaceExtension_Extension_TextSliceFlatAll = USCoreRaceExtension_Extension_TextSliceFlat & { + readonly url: "text"; +} import { isRawExtensionInput, @@ -1783,7 +1822,6 @@ import { setArraySlice, getArraySlice, ensureSliceDefaults, - stripMatchKeys, wrapSliceChoice, unwrapSliceChoice, isExtension, @@ -1970,37 +2008,37 @@ export class USCoreRaceExtensionProfile { return this } - public getExtensionOmbCategory(mode: 'flat'): USCoreRaceExtension_Extension_OmbCategorySliceFlat | undefined; + public getExtensionOmbCategory(mode: 'flat'): USCoreRaceExtension_Extension_OmbCategorySliceFlatAll | undefined; public getExtensionOmbCategory(mode: 'raw'): Extension | undefined; - public getExtensionOmbCategory(): USCoreRaceExtension_Extension_OmbCategorySliceFlat | undefined; - public getExtensionOmbCategory (mode: 'flat' | 'raw' = 'flat'): USCoreRaceExtension_Extension_OmbCategorySliceFlat | Extension | undefined { + public getExtensionOmbCategory(): USCoreRaceExtension_Extension_OmbCategorySliceFlatAll | undefined; + public getExtensionOmbCategory (mode: 'flat' | 'raw' = 'flat'): USCoreRaceExtension_Extension_OmbCategorySliceFlatAll | Extension | undefined { const match = USCoreRaceExtensionProfile.ombCategorySliceMatch const item = getArraySlice(this.resource.extension, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["url"], "valueCoding") + return unwrapSliceChoice(item, ["url"], "valueCoding") } - public getExtensionDetailed(mode: 'flat'): USCoreRaceExtension_Extension_DetailedSliceFlat | undefined; + public getExtensionDetailed(mode: 'flat'): USCoreRaceExtension_Extension_DetailedSliceFlatAll | undefined; public getExtensionDetailed(mode: 'raw'): Extension | undefined; - public getExtensionDetailed(): USCoreRaceExtension_Extension_DetailedSliceFlat | undefined; - public getExtensionDetailed (mode: 'flat' | 'raw' = 'flat'): USCoreRaceExtension_Extension_DetailedSliceFlat | Extension | undefined { + public getExtensionDetailed(): USCoreRaceExtension_Extension_DetailedSliceFlatAll | undefined; + public getExtensionDetailed (mode: 'flat' | 'raw' = 'flat'): USCoreRaceExtension_Extension_DetailedSliceFlatAll | Extension | undefined { const match = USCoreRaceExtensionProfile.detailedSliceMatch const item = getArraySlice(this.resource.extension, match) if (!item) return undefined if (mode === 'raw') return item - return unwrapSliceChoice(item, ["url"], "valueCoding") + return unwrapSliceChoice(item, ["url"], "valueCoding") } - public getExtensionText(mode: 'flat'): USCoreRaceExtension_Extension_TextSliceFlat | undefined; + public getExtensionText(mode: 'flat'): USCoreRaceExtension_Extension_TextSliceFlatAll | undefined; public getExtensionText(mode: 'raw'): Extension | undefined; - public getExtensionText(): USCoreRaceExtension_Extension_TextSliceFlat | undefined; - public getExtensionText (mode: 'flat' | 'raw' = 'flat'): USCoreRaceExtension_Extension_TextSliceFlat | Extension | undefined { + public getExtensionText(): USCoreRaceExtension_Extension_TextSliceFlatAll | undefined; + public getExtensionText (mode: 'flat' | 'raw' = 'flat'): USCoreRaceExtension_Extension_TextSliceFlatAll | Extension | undefined { const match = USCoreRaceExtensionProfile.textSliceMatch const item = getArraySlice(this.resource.extension, match) if (!item) return undefined if (mode === 'raw') return item - return stripMatchKeys(item, ["url"]) + return item as unknown as USCoreRaceExtension_Extension_TextSliceFlatAll } // Validation diff --git a/test/api/write-generator/multi-package/__snapshots__/local-package.test.ts.snap b/test/api/write-generator/multi-package/__snapshots__/local-package.test.ts.snap index 09cf8599..0057d278 100644 --- a/test/api/write-generator/multi-package/__snapshots__/local-package.test.ts.snap +++ b/test/api/write-generator/multi-package/__snapshots__/local-package.test.ts.snap @@ -38,7 +38,10 @@ import type { Organization } from "../../hl7-fhir-r4-core/Organization"; import type { Patient } from "../../hl7-fhir-r4-core/Patient"; export type ExampleTypedBundle_Entry_PatientEntrySliceFlat = BundleEntry; +export type ExampleTypedBundle_Entry_PatientEntrySliceFlatAll = ExampleTypedBundle_Entry_PatientEntrySliceFlat; + export type ExampleTypedBundle_Entry_OrganizationEntrySliceFlat = BundleEntry; +export type ExampleTypedBundle_Entry_OrganizationEntrySliceFlatAll = ExampleTypedBundle_Entry_OrganizationEntrySliceFlat; import { ensureProfile, @@ -66,7 +69,9 @@ export class ExampleTypedBundleProfile { static readonly canonicalUrl = "http://example.org/fhir/StructureDefinition/ExampleTypedBundle"; private static readonly PatientEntrySliceMatch: Record = {"resource":{"resourceType":"Patient"}}; - private static readonly OrganizationEntrySliceMatch: Record = {"resource":{"resourceType":"Organization"}}; + private static readonly OrganizationEntrySliceMatch: Record = { + "resource": {"resourceType":"Organization"}, + } private resource: Bundle; @@ -141,26 +146,26 @@ export class ExampleTypedBundleProfile { return this } - public getPatientEntry(mode: 'flat'): ExampleTypedBundle_Entry_PatientEntrySliceFlat | undefined; + public getPatientEntry(mode: 'flat'): ExampleTypedBundle_Entry_PatientEntrySliceFlatAll | undefined; public getPatientEntry(mode: 'raw'): BundleEntry | undefined; - public getPatientEntry(): ExampleTypedBundle_Entry_PatientEntrySliceFlat | undefined; - public getPatientEntry (mode: 'flat' | 'raw' = 'flat'): ExampleTypedBundle_Entry_PatientEntrySliceFlat | BundleEntry | undefined { + public getPatientEntry(): ExampleTypedBundle_Entry_PatientEntrySliceFlatAll | undefined; + public getPatientEntry (mode: 'flat' | 'raw' = 'flat'): ExampleTypedBundle_Entry_PatientEntrySliceFlatAll | BundleEntry | undefined { const match = ExampleTypedBundleProfile.PatientEntrySliceMatch const item = getArraySlice(this.resource.entry, match) if (!item) return undefined if (mode === 'raw') return item as BundleEntry - return item as ExampleTypedBundle_Entry_PatientEntrySliceFlat + return item as unknown as ExampleTypedBundle_Entry_PatientEntrySliceFlatAll } - public getOrganizationEntry(mode: 'flat'): ExampleTypedBundle_Entry_OrganizationEntrySliceFlat | undefined; + public getOrganizationEntry(mode: 'flat'): ExampleTypedBundle_Entry_OrganizationEntrySliceFlatAll | undefined; public getOrganizationEntry(mode: 'raw'): BundleEntry | undefined; - public getOrganizationEntry(): ExampleTypedBundle_Entry_OrganizationEntrySliceFlat | undefined; - public getOrganizationEntry (mode: 'flat' | 'raw' = 'flat'): ExampleTypedBundle_Entry_OrganizationEntrySliceFlat | BundleEntry | undefined { + public getOrganizationEntry(): ExampleTypedBundle_Entry_OrganizationEntrySliceFlatAll | undefined; + public getOrganizationEntry (mode: 'flat' | 'raw' = 'flat'): ExampleTypedBundle_Entry_OrganizationEntrySliceFlatAll | BundleEntry | undefined { const match = ExampleTypedBundleProfile.OrganizationEntrySliceMatch const item = getArraySlice(this.resource.entry, match) if (!item) return undefined if (mode === 'raw') return item as BundleEntry - return item as ExampleTypedBundle_Entry_OrganizationEntrySliceFlat + return item as unknown as ExampleTypedBundle_Entry_OrganizationEntrySliceFlatAll } // Validation