Role. You are a senior TypeScript test engineer. @fhir-dsl/types ships
only type definitions — no runtime code — so your tests are
compile-only (*.test-d.ts) and run via vitest's typecheck integration.
No source changes. No new runtime dependencies.
fhir-dsl is a type-safe FHIR monorepo. @fhir-dsl/types is the
foundation package: it defines FHIR primitives (id, dateTime, code,
uri, …), element/extension types, base Resource / Bundle / OperationOutcome
shapes, and the SearchParam<Type, Value> helpers consumed by the
generator's emitted code.
The package does not contain generated resource types — those are
emitted by @fhir-dsl/generator into the user's project.
Public surface (packages/types/src/index.ts):
primitives.ts— primitive string aliases:FhirString,FhirCode<T>,FhirDateTime,FhirInstant,FhirInteger,FhirDecimal,FhirPositiveInt,FhirId,FhirUri,FhirCanonical,FhirUuid, etc.datatypes.ts—Element,Extension,Reference<T>,Period,HumanName,Address,Coding,CodeableConcept,Quantity,Money,Ratio,Attachment,Identifier,Meta,Narrative.search-param-types.ts—SearchParam<Type, Value>,SearchPrefixes<Type>, and the param-type enum.
packages/types/src/index.tspackages/types/src/primitives.tspackages/types/src/datatypes.tspackages/types/src/search-param-types.ts
None. This package has zero tests today.
Write compile-only tests in packages/types/test/*.test-d.ts. Use
expectTypeOf from vitest or tsd-style @ts-expect-error assertions.
FhirIdis assignable from a string but not from a number.FhirCode<"male" | "female">narrows —"other"is not assignable. Without a generic arg,FhirCodeis plain string.FhirPositiveInt,FhirInteger,FhirDecimalare each numeric brands. Assigning a non-number errors.FhirDateTimeaccepts the ISO 8601 forms listed in the FHIR R4 primitive spec (partialYYYY,YYYY-MM, full with timezone), and rejects garbage if branded.- Primitive aliases preserve assignment compatibility with their
underlying TS type (a plain
stringcan flow intoFhirUri, for instance) — confirm so consumers don't need ceremony for literals.
Element.extension?: Extension[]— the field is optional, array, and each extension carries aurl+ a value.Reference<T>narrows whenTis a specific resource type and widens to unknown when omitted.Coding.codeis aFhirCode; narrowingCoding<"active" | "inactive">(if the generic exists) restrictscode.CodeableConcept.coding?: Coding[]and.text?: FhirStringmatch the FHIR R4 shape.HumanName,Address,Identifier,Period,Quantity,Money,Ratio,Attachment— one positive + one@ts-expect-errornegative case each (e.g.Period.startrejects a non-date value).Meta.profile?: FhirCanonical[]andMeta.tag?: Coding[]match the spec.
SearchParam<"string", string>andSearchParam<"token", string>produce distinct types — a token param value with a system-pipe form is still a string, but the wrapper type tag differs.SearchPrefixes<"date">includes"eq" | "ne" | "gt" | "lt" | "ge" | "le" | "sa" | "eb" | "ap";SearchPrefixes<"string">is narrower (no numeric prefixes).- Unknown param types (
SearchParam<"bogus", any>) fail to compile.
- FHIR R4 primitive types: https://www.hl7.org/fhir/R4/datatypes.html#primitive — exact regex and value-space rules for each primitive.
- FHIR R4 complex types: https://www.hl7.org/fhir/R4/datatypes.html#complex.
- FHIR search parameter types + prefixes: https://www.hl7.org/fhir/R4/search.html#prefix.
- vitest typecheck tests: https://vitest.dev/guide/testing-types.
expectTypeOfAPI: https://vitest.dev/api/expect-typeof.html.
- Every test file ends in
.test-d.tsso vitest's typecheck integration picks it up. Compile-only — noexpect(...), no runtime. - Negative assertions use
@ts-expect-errorimmediately above the failing expression. The expression on the next line must actually fail — otherwise vitest fails the typecheck test (the expect-error becomes unused). - No
any, noascasts in the assertions themselves. UseexpectTypeOf<T>().toEqualTypeOf<U>().
- Read the source.
- Write tests in
packages/types/test/:primitives.test-d.tsdatatypes.test-d.tssearch-param-types.test-d.ts
- Gates:
pnpm test # runs typecheck tests too, per vitest.config.ts pnpm lint pnpm -r typecheck
- Every scenario above has ≥1 type-level assertion.
pnpm testpasses vitest's typecheck integration for this package.pnpm lintandpnpm -r typecheckgreen.- No source changes.
- Adding new primitive brands.
- Runtime behavior — there is none.
- Generated resource types — they live in the generator's output, not here.