Skip to content

TS: import only the helpers and types a profile module uses - #256

Draft
Palid wants to merge 8 commits into
atomic-ehr:mainfrom
Palid:ts/profile-imports-from-body
Draft

Palid wants to merge 8 commits into
atomic-ehr:mainfrom
Palid:ts/profile-imports-from-body

Conversation

@Palid

@Palid Palid commented Oct 1, 2026

Copy link
Copy Markdown

Profile modules imported fixed bundles of helpers and types, picked by coarse structural conditions (any field, any slice, any extension with a url) before the class body was written. Now the validate() body is collected first, and every import is derived from what the module actually emits.

Closes #254

Profile imports

  • collectValidateBody returns the validate() error and warning expressions plus the names of the validate* helpers they call; the profile-helpers import takes its validators from that set
  • validate() declares profileName and res only when it has an expression to emit
  • every other helper is imported under the condition its emitter uses:
    • setArraySlice/getArraySlice only for a bounded array slice, setArraySliceAll/getArraySliceAll only for an unbounded one (isUnboundedSlice, now shared with the slice setters and getters), ensureSliceDefaults only with slice auto-fields
    • the extension helpers read collectExtensionMethodInfos, the same list the extension methods are generated from: isExtension only where an emitted branch checks it (extensionProfileHasFlatInput for complex extensions), getExtensionValue only for single-value extensions, pushExtension only for repeating ones
    • isRawExtensionInput and ensureProfile no longer check for a canonical url
  • type and class imports:
    • complex sub-extension value types only when the extension's profile has no flat input
    • an extension without a url adds nothing
    • the extension profile class only for complex and single-value extensions; its …ProfileFlat type only for complex ones
  • test/api/write-generator/profile-unused-imports.test.ts pins each case

The validate bundle was imported whole whenever a profile had a field; birthPlace calls four of the ten:

 import {
     applyFixedValue,
     validateRequired,
-    validateExcluded,
     validateFixedValue,
-    validateSliceCardinality,
-    validateSliceFields,
-    validateEnum,
-    validateReference,
     validateChoiceRequired,
     validateChoiceProhibited,
-    validateMustSupport,
 } from "../../profile-helpers";

A profile with nothing to validate still declared the two locals the expressions read (NotedPatient):

     validate(): { errors: string[]; warnings: string[] } {
-        const profileName = "NotedPatient"
-        const res = this.resource
         return {
             errors: [],
             warnings: [],

noUnusedLocals

  • the root tsconfig.json turns it on; every example tsconfig extends the root one, so the example typechecks in CI now fail on an unused import or local in generated output (the committed us-core output had 97 TS6133 before this branch, 0 now)
  • removed the five hand-written locals it flagged: _dateTimeType, _periodType, _rangeType, _basePackageInfo, and _validNote (now void vFlat!.note.trim())
  • the @ts-expect-error over const _note: string = flat!.note would have been satisfied by TS6133 alone, so it is now the expression void flat!.note.trim()
     // Some stricter flags (disabled by default)
-    "noUnusedLocals": false,
+    "noUnusedLocals": true,
     "noUnusedParameters": false,

CDA Reference import

  • generateType renders Reference, Coding and CodeableConcept with the hardcoded <T extends string = string> and drops their IR generic params, but generateDependenciesImports still imported the constraint types of those params
  • it now skips constraints of dropped params that nothing else in the module names (droppedGenericConstraintUrls)

hl7-cda-uv-core/Reference.ts in the ccda output:

-import type { Base } from "../hl7-fhir-r5-core/Base";
 import type { BL } from "../hl7-cda-uv-core/BL";
 import type { ExternalAct } from "../hl7-cda-uv-core/ExternalAct";

Reach

  • examples/typescript-r4-us-core: the 17 committed profile modules, import removals only
  • example snapshots: typescript-custom-packages, on-the-fly norge-r4 and ccda
  • test snapshots under test/api/write-generator/
  • the on-the-fly trees (norge-r4, kbv-r4, kbv-condition-diagnosis, ccda) were regenerated and typecheck with zero TS6133/TS6192/TS6196
  • no change to Python, C# or Mustache output

Palid added 8 commits October 1, 2026 01:17
… locals

Records today's import blocks and validate() output for five causes:
- the ten-name validate bundle imported when one validator or none is called
- a complex extension resolving to a flat-input profile still imports its sub-extension value type (CodeableConcept)
- an extension slice without a url imports Extension and ensurePath unused
- a generic extension imports its profile class unused
- a profile with nothing to validate emits the profileName/res locals
- collectValidateBody collects the validate() expressions and the validate* helpers they call; the profile-helpers import takes its validate* names from that set, and validate() declares profileName/res only when it has an expression
- every other helper is imported under the condition its emitter uses: ensureSliceDefaults, setArraySlice/getArraySlice, isExtension, getExtensionValue, pushExtension, ensurePath and extractComplexExtension; isRawExtensionInput and ensureProfile no longer depend on the canonical url
- collectExtensionMethodInfos is the one list of url'd extensions the extension methods and the imports both read, so an extension without a url imports nothing
- a complex extension resolving to a flat-input profile no longer imports its sub-extension value types; a generic extension no longer imports its profile class
Flips the pin to the intended import blocks and the local-free empty validate(), and updates the snapshots whose profile modules lose unused helper and type imports.
… its params

generateType renders any schema named Reference, Coding or CodeableConcept with the hardcoded `<T extends string>` and drops its IR generic params, but generateDependenciesImports still imported the constraint type only those params named. The CDA Reference imported `Base` (r5) without using it.
Every example tsconfig extends the root one, so an unused import in generated output now fails the example typecheck. Drops the unused test fixtures it flags (_dateTimeType, _periodType, _rangeType, _basePackageInfo) and writes the vflat member check in _flatContractTypes as an expression.
- examples/typescript-r4-us-core/fhir-types: 17 profile modules
- examples/typescript-custom-packages/__snapshots__: profile-complex-extension-flat, profile-typed-bundle
- examples/on-the-fly/norge-r4/__snapshots__: kjernejournal-profiles
- examples/on-the-fly/ccda/__snapshots__: uv-extensions-r4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TS: generated profiles import unused helpers and declare unused locals (TS6133 under noUnusedLocals)

1 participant