From 2872cee3c8fc125b202ef19ee2ea171d18f967f2 Mon Sep 17 00:00:00 2001 From: Aleksandr Penskoi Date: Wed, 8 Apr 2026 10:12:21 +0200 Subject: [PATCH 1/3] ref: Remove dead stripMatchKeys export from profile-helpers --- .../writer-generator/typescript/profile-helpers.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/assets/api/writer-generator/typescript/profile-helpers.ts b/assets/api/writer-generator/typescript/profile-helpers.ts index e02bbb12..91cfb01f 100644 --- a/assets/api/writer-generator/typescript/profile-helpers.ts +++ b/assets/api/writer-generator/typescript/profile-helpers.ts @@ -203,19 +203,6 @@ export const extractComplexExtension = >( // Slice helpers // --------------------------------------------------------------------------- -/** - * Remove discriminator keys from a slice element, returning only the - * user-supplied portion. Used by slice getters so callers see a clean object - * without the fixed discriminator values baked in. - */ -export const stripMatchKeys = (slice: object, matchKeys: string[]): T => { - const result = { ...slice } as Record; - for (const key of matchKeys) { - delete result[key]; - } - return result as T; -}; - /** * Wrap a flat input object under a choice-type key before inserting into a * slice. For example, a Quantity value destined for `valueQuantity` is From 8ecceaf1b8014fb1bd6d8731d99b1073f738c023 Mon Sep 17 00:00:00 2001 From: Aleksandr Penskoi Date: Wed, 8 Apr 2026 10:12:21 +0200 Subject: [PATCH 2/3] docs: Add TypeScript Profile API section to CLAUDE.md Document SliceFlat/SliceFlatAll types, unbounded slice array API, Reference for family types, and slice field validation. --- CLAUDE.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 48bd12b9..d1ad5d08 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -252,6 +252,47 @@ assets/api/writer-generator/ - Use assets for static runtime code shared across all generated profiles (helpers, validators, base models) - Use programmatic generation (`w.lineSM()`, `w.curlyBlock()`) for code that varies per schema/profile +## TypeScript Profile API + +### Slice Types + +Each non-type-discriminated slice generates two types: +- **`SliceFlat`** — setter input, discriminator fields omitted (auto-applied by setter) +- **`SliceFlatAll`** — getter return, extends `SliceFlat` with readonly discriminator literals + +```typescript +// Setter input — only user data +export type VSCatSliceFlat = Omit; +// Getter return — includes discriminator values +export type VSCatSliceFlatAll = VSCatSliceFlat & { + readonly coding: [{ code: "vital-signs"; system: "http://...observation-category" }]; +} +``` + +Type-discriminated slices (e.g. `BundleEntry`) use the typed base type directly — no `SliceFlat`/`SliceFlatAll` generated. + +### Unbounded Slices (max: *) + +Slices with `max: *` use array-based API: +- **Setter**: `setOrganizationEntry(entries[])` — replaces all matched elements +- **Getter**: `getOrganizationEntry()` — returns `T[] | undefined` + +Single-element slices (`max: 1`) keep the existing single-item API. + +### Reference Types for Family Types + +When a reference target is a family type (e.g. `Resource`, `DomainResource`), the generated type uses `Reference` instead of `Reference<"Resource">`. This makes narrower profile references like `Reference<"Patient">` assignable to the base type field. + +Detection uses `mkIsFamilyType(tsIndex)` which checks `schema.typeFamily.resources.length > 0`. + +### Slice Field Validation + +`validate()` checks required fields inside matched slice elements via `validateSliceFields`. For constrained choice slices (e.g. BP `component.value[x]` restricted to `valueQuantity`), the variant is validated as required: + +``` +"observation-bp.component[SystolicBP].valueQuantity is required" +``` + ## Common Development Patterns ### Adding a New Generator Feature From fa604208747906a5a0bfba263f5dcd07818e9d5f Mon Sep 17 00:00:00 2001 From: Aleksandr Penskoi Date: Wed, 8 Apr 2026 10:12:21 +0200 Subject: [PATCH 3/3] chore: Regenerate examples and snapshots after stripMatchKeys removal --- .../typescript-r4/fhir-types/profile-helpers.ts | 13 ------------- .../fhir-types/profile-helpers.ts | 13 ------------- 2 files changed, 26 deletions(-) diff --git a/examples/typescript-r4/fhir-types/profile-helpers.ts b/examples/typescript-r4/fhir-types/profile-helpers.ts index e02bbb12..91cfb01f 100644 --- a/examples/typescript-r4/fhir-types/profile-helpers.ts +++ b/examples/typescript-r4/fhir-types/profile-helpers.ts @@ -203,19 +203,6 @@ export const extractComplexExtension = >( // Slice helpers // --------------------------------------------------------------------------- -/** - * Remove discriminator keys from a slice element, returning only the - * user-supplied portion. Used by slice getters so callers see a clean object - * without the fixed discriminator values baked in. - */ -export const stripMatchKeys = (slice: object, matchKeys: string[]): T => { - const result = { ...slice } as Record; - for (const key of matchKeys) { - delete result[key]; - } - return result as T; -}; - /** * Wrap a flat input object under a choice-type key before inserting into a * slice. For example, a Quantity value destined for `valueQuantity` is diff --git a/examples/typescript-us-core/fhir-types/profile-helpers.ts b/examples/typescript-us-core/fhir-types/profile-helpers.ts index e02bbb12..91cfb01f 100644 --- a/examples/typescript-us-core/fhir-types/profile-helpers.ts +++ b/examples/typescript-us-core/fhir-types/profile-helpers.ts @@ -203,19 +203,6 @@ export const extractComplexExtension = >( // Slice helpers // --------------------------------------------------------------------------- -/** - * Remove discriminator keys from a slice element, returning only the - * user-supplied portion. Used by slice getters so callers see a clean object - * without the fixed discriminator values baked in. - */ -export const stripMatchKeys = (slice: object, matchKeys: string[]): T => { - const result = { ...slice } as Record; - for (const key of matchKeys) { - delete result[key]; - } - return result as T; -}; - /** * Wrap a flat input object under a choice-type key before inserting into a * slice. For example, a Quantity value destined for `valueQuantity` is