Skip to content

Improve type coverage by generating types#337

Open
ziahamza wants to merge 17 commits intokingstinct:masterfrom
ziahamza:generate-healthkit-types
Open

Improve type coverage by generating types#337
ziahamza wants to merge 17 commits intokingstinct:masterfrom
ziahamza:generate-healthkit-types

Conversation

@ziahamza
Copy link
Copy Markdown

This adds in a type generator to make Apple’s SDK become the main source of truth

The generator reads HealthKit symbol graphs and SDK headers, builds a normalized schema, and generates both TypeScript (and a bit of Swift) from that schema.

The following types have been tightened as a result:

  • category samples now narrow by identifier
  • quantity samples now narrow by identifier/unit/known metadata
  • workouts and workout events now expose generated typed metadata

It also updates test.yml to make sure the types stay up to date to the pinned Xcode / SDK version

It does not cover everything, so there is a fallback to get some info from headers directly:

  • category identifier -> value enum mapping
  • metadata key payload semantics/applicability
  • writeability policy in a few places

I still keep raw metadata and legacy flattened metadataX fields for compatibility.

The generated code is a bit large, but can be removed from repo if it's preferred to keep it in codegen (but that adds a hard dependency to have exact xcode version from author and CI checks need to move to Mac runners instead of ubuntu)

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 25, 2026

🦋 Changeset detected

Latest commit: 56e6e4c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@kingstinct/react-native-healthkit Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 25, 2026

Open in StackBlitz

npm i https://pkg.pr.new/kingstinct/react-native-healthkit/@kingstinct/react-native-healthkit@337

commit: 56e6e4c

@ziahamza
Copy link
Copy Markdown
Author

Updates since the last time:

  • converged on a single metadata field, and nuked metadataX fields
  • Added a basic end to end test, and basic support for Zod schemas to validate runtime objects match the type system in those tests

@ziahamza ziahamza changed the title [WIP] Improve type coverage by generating types Improve type coverage by generating types Mar 29, 2026
@ziahamza ziahamza marked this pull request as ready for review March 29, 2026 11:16
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an SDK-driven HealthKit type generator and switches large parts of the library to use generated identifiers/units/value enums + typed metadata as the primary surface, with CI checks to keep generated artifacts in sync with the pinned Xcode/SDK.

Changes:

  • Introduce HealthKit SDK parsing + schema generation, emitting TypeScript, Swift helpers, and contract schemas.
  • Tighten typings across quantity/category/workout APIs (typed metadata, identifier/unit/value narrowing, typed module surfaces).
  • Add type-tests + CI/workflow steps to verify generated artifacts and run runtime contract scenarios in the example app.

Reviewed changes

Copilot reviewed 66 out of 72 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/react-native-healthkit/tsconfig.type-tests.json Add a dedicated TS config for compile-time type tests.
packages/react-native-healthkit/src/utils/subscribeToQuantitySamples.ts Generic callback typing tied to quantity identifier.
packages/react-native-healthkit/src/utils/getQuantitySampleById.ts Narrow unit param type via UnitForIdentifier<T>.
packages/react-native-healthkit/src/utils/getPreferredUnit.ts Generic return type for preferred unit per identifier.
packages/react-native-healthkit/src/utils/getMostRecentWorkout.ts Return typed workout proxy shape.
packages/react-native-healthkit/src/utils/getMostRecentQuantitySample.ts Narrow unit param type via UnitForIdentifier<T>.
packages/react-native-healthkit/src/types/Workouts.ts Re-export generated enums + introduce typed workout metadata/event typing.
packages/react-native-healthkit/src/types/WeatherCondition.ts Re-export generated WeatherCondition enum.
packages/react-native-healthkit/src/types/Subscriptions.ts Make subscription callback payloads generic over identifiers.
packages/react-native-healthkit/src/types/StateOfMind.ts Add typed-metadata sample/anchor response variants.
packages/react-native-healthkit/src/types/Shared.ts Replace flattened metadata fields with typed-metadata helpers + known metadata types.
packages/react-native-healthkit/src/types/QueryOptions.ts Add generic unit-bearing query options + StringUnit variants.
packages/react-native-healthkit/src/types/QuantityTypeIdentifier.ts Re-export generated identifier unions.
packages/react-native-healthkit/src/types/QuantityType.ts Use generated unit mapping + add typed anchor response + generic statistics options.
packages/react-native-healthkit/src/types/QuantitySample.ts Add QuantitySampleTyped<T> + per-identifier typed metadata mapping.
packages/react-native-healthkit/src/types/MetadataEnums.ts Export generated metadata enums for consumption.
packages/react-native-healthkit/src/types/Medication.ts Add typed medication event metadata + typed anchor response.
packages/react-native-healthkit/src/types/InterfaceVerification.ts Extend interface verification to include method assignability checks.
packages/react-native-healthkit/src/types/index.ts Export new types (Medication, MetadataEnums).
packages/react-native-healthkit/src/types/HeartbeatSeries.ts Add typed-metadata sample/anchor response variants.
packages/react-native-healthkit/src/types/ElectrocardiogramSample.ts Add typed-metadata sample/anchor response variants.
packages/react-native-healthkit/src/types/CorrelationType.ts Move metadata fields into typed metadata + add typed anchor response.
packages/react-native-healthkit/src/types/CategoryTypeIdentifier.ts Re-export generated identifier unions.
packages/react-native-healthkit/src/types/CategoryType.ts Use generated value enums + per-identifier typed metadata/value typing.
packages/react-native-healthkit/src/type-tests/generated-typing.ts Add compile-time assertions for generated typing behavior.
packages/react-native-healthkit/src/specs/QuantityTypeModule.nitro.ts Add typed module interface + constrain base options to string-units.
packages/react-native-healthkit/src/specs/CategoryTypeModule.nitro.ts Restrict save identifier to writeable identifiers + return typed samples.
packages/react-native-healthkit/src/modules.ts Cast QuantityTypes module to typed interface.
packages/react-native-healthkit/src/hooks/useSubscribeToQuantitySamples.ts Generic callback typing tied to identifier.
packages/react-native-healthkit/src/hooks/useStatisticsForQuantity.ts Narrow unit param type via UnitForIdentifier<T>.
packages/react-native-healthkit/src/hooks/useQuantitySampleById.ts Return typed quantity samples + narrow unit option.
packages/react-native-healthkit/src/hooks/useMostRecentWorkout.ts Store typed workout proxy in state.
packages/react-native-healthkit/src/hooks/useMostRecentQuantitySample.ts Return typed quantity sample + narrow unit param.
packages/react-native-healthkit/src/healthkit.ts Update non-iOS fallbacks to the new typed generic signatures.
packages/react-native-healthkit/src/healthkit.ios.ts Cast bound native methods to typed return shapes for the JS API.
packages/react-native-healthkit/src/generated/healthkit.generated.ts Add generated TS types/enums/constants sourced from the SDK.
packages/react-native-healthkit/src/generated/healthkit-schema.json Add generated normalized schema JSON used as source-of-truth artifact.
packages/react-native-healthkit/scripts/verify-healthkit-sdk.ts Add invariant checks against the pinned SDK schema extraction.
packages/react-native-healthkit/scripts/healthkit-sdk.ts Implement SDK/header/symbolgraph loading + artifact writing/formatting.
packages/react-native-healthkit/scripts/healthkit-schema/identifier-overrides.json Add overrides for read-only identifiers.
packages/react-native-healthkit/scripts/generate-healthkit-cli.ts Add CLI entry for generation + formatting.
packages/react-native-healthkit/package.json Add generation/verification scripts + generated artifact checks + type-tests in typecheck.
packages/react-native-healthkit/ios/WorkoutProxy.swift Remove flattened metadata fields; surface raw metadata only.
packages/react-native-healthkit/ios/StateOfMindModule.swift Remove flattened metadata fields; serialize metadata map once.
packages/react-native-healthkit/ios/Serializers.swift Improve metadata serialization (NSNumber/Date handling) + extend unknown quantity units.
packages/react-native-healthkit/ios/QuantityTypeModule.swift Use string-unit option types and adjust field ordering in response serialization.
packages/react-native-healthkit/ios/PredicateHelpers.swift Fix argument ordering when constructing workout filter base.
packages/react-native-healthkit/ios/MedicationModule.swift Remove flattened metadata fields; serialize metadata map once.
packages/react-native-healthkit/ios/HeartbeatSeriesModule.swift Remove flattened metadata fields; serialize metadata map once.
packages/react-native-healthkit/ios/generated/HealthkitGenerated.swift Add generated Swift helpers to identify boolean/numeric metadata keys.
packages/react-native-healthkit/ios/ElectrocardiogramModule.swift Remove flattened metadata fields; serialize metadata map once.
packages/react-native-healthkit/ios/CorrelationTypeModule.swift Move foodType into metadata map; remove flattened metadata fields.
packages/react-native-healthkit/ios/CategoryTypeModule.swift Restrict save identifier to writeable identifiers.
package.json Add root script to run example “contracts” harness.
bun.lock Update lockfile (incl. workspace version bump and added deps).
biome.json Exclude additional build artifacts and a specific env d.ts from formatting.
apps/example/scripts/run-healthkit-contracts.sh Add simulator-driven contract runner script.
apps/example/package.json Add contracts script and zod dependency for contract validation.
apps/example/contracts/scenarios.ts Add runtime contract scenarios for quantity/category/workout round-trips.
apps/example/contracts/report.ts Write contract results to the simulator Documents directory.
apps/example/contracts/launchCommand.ts Read/clear simulator launch command file used to auto-run contracts.
apps/example/contracts/index.ts Add Zod-based validation/assert helpers around generated contract schemas.
apps/example/contracts/generated/healthkit.contract.generated.ts Add generated Zod schemas + per-identifier metadata expectations.
apps/example/constants/AllUsedIdentifiersInApp.ts Ensure identifiers used in contracts are included in authorization lists.
apps/example/app/contracts.tsx Add an in-app UI to run/autorun contract scenarios and write reports.
apps/example/app/auth.tsx Route to contract harness based on launch command file + auto-request auth.
apps/example/app/(tabs)/index.tsx Add an entry point to open the contracts screen.
apps/example/app/_layout.tsx Auto-route into the contracts screen based on launch command file.
.gitignore Ignore Swift build artifacts (.build, .swiftpm).
.github/workflows/test.yml Add generated artifact verification + run contract harness in CI.
.changeset/typed-healthkit-bindings.md Add major changeset documenting metadata/type surface breaking changes.

Copy link
Copy Markdown
Member

@robertherber robertherber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR @ziahamza, I think this will be a great improvement!

Fixed some repo stuff, the CI workflow for test was actually targeting master.. 😬

Copy link
Copy Markdown
Member

@robertherber robertherber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm 🥳

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.

3 participants