Skip to content

feat(core-types): Create @rnx-kit/core-types package and consume types from that package#3961

Open
JasonVMo wants to merge 19 commits intomainfrom
user/jasonvmo/core-types
Open

feat(core-types): Create @rnx-kit/core-types package and consume types from that package#3961
JasonVMo wants to merge 19 commits intomainfrom
user/jasonvmo/core-types

Conversation

@JasonVMo
Copy link
Collaborator

Description

This change creates a new @rnx-kit/core-types package for core configuration types, manifest types, lint types, and so on. This avoids pulling in implementations when not needed and generally cleans up the dependency graph.

There are also several places where using rnx-kit packages via an API from outside rnx-kit weren't exposing types correctly because the types came from a devDependency package (because the implementation wasn't needed) but as a result the types weren't being exported correctly. Having a lightweight types package allows for these to be correctly marked as dependencies causing the types to resolve correctly from outside the repo.

  • despite the move, all packages that previously exported types still do so, they just now do it via re-exporting the types from the new package.

KitConfig and Supporting Types

The KitConfig was coming out of the @rnx-kit/config package which was pulling in several metro plugin packages for the types. Some plugin types were defined in the config package, some were defined locally, regardless it created a bit of a dependency snarl. These were the primary types moved into the new package.

  • the plugin configurations that were still in their own packages were moved into the core-types
  • esbuild and metro are marked as optional peer dependencies which allows those types to be fulfilled when necessary without creating a costly transitive dependency install chain.
  • the align deps config was separated out and defined on its own with the ability to template it with extended capabilities. This makes creating custom presets more ergonomic.

Package Manifest Types

The PackageManifest type has been moved from tools-node into core-types. It has also been greatly improved by:

  • adding most of the standard package.json types
  • adding a typed entry for the KitConfig (this was impossible due to circular dependency issues before)

I also added a PackageData type which is designed as a parameter type for functions that want to take a folder and manifest pairing which can be fulfilled by PackageInfo or by other implementations. This will be used in subsequent changes.

AllPlatforms

I also moved the AllPlatforms type here, and changed it to be based on an array definition ensuring those stay in sync.

Test plan

This is almost 100% type only (with the exception of the ALL_PLATFORM_VALUES array so automated tests + pipelines should be sufficient.

@github-actions github-actions bot added feature: metro This is related to Metro feature: align-deps This is related to align-deps feature: cli This is related to CLI labels Feb 10, 2026
@JasonVMo JasonVMo enabled auto-merge (squash) February 10, 2026 20:00
Copy link
Member

@tido64 tido64 left a comment

Choose a reason for hiding this comment

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

In my experience, these kinds of catch-all type packages tend to accumulate unrelated or legacy definitions over time. Without clear, enforced criteria for what qualifies as "core", the package can gradually become a dumping ground for anything that’s shared somewhere, including types tied to features that later change or disappear. When there’s also no explicit policy for ownership, review standards, and deprecation/removal, it becomes hard to keep the package coherent and healthy.

The long-term risk is that the module turns into a tightly coupled dependency hub: changes become high-blast-radius, the package becomes intimidating to modify, and it eventually slows down refactoring because it's easier to add "just one more type" than to untangle things properly.

Instead, I think we should prefer package-/domain-specific type packages. If another package needs to consume types from @rnx-kit/config, we should publish something like @rnx-kit/config-types and keep the scope intentionally narrow and owned by the same domain. This keeps dependencies and responsibility clear, avoids a single "everything depends on this" package, and allows types to evolve with the package they represent.

If we go this route, the guideline could be:

  • No centralized types package.
  • Types should live with their owning package, and only be extracted into a *-types package when there’s a clear consumer need outside that package.
  • Each *-types package should have an explicit scope tied to that domain (e.g., config-related types only).

@JasonVMo
Copy link
Collaborator Author

In my experience, these kinds of catch-all type packages tend to accumulate unrelated or legacy definitions over time. Without clear, enforced criteria for what qualifies as "core", the package can gradually become a dumping ground for anything that’s shared somewhere, including types tied to features that later change or disappear. When there’s also no explicit policy for ownership, review standards, and deprecation/removal, it becomes hard to keep the package coherent and healthy.

The long-term risk is that the module turns into a tightly coupled dependency hub: changes become high-blast-radius, the package becomes intimidating to modify, and it eventually slows down refactoring because it's easier to add "just one more type" than to untangle things properly.

Instead, I think we should prefer package-/domain-specific type packages. If another package needs to consume types from @rnx-kit/config, we should publish something like @rnx-kit/config-types and keep the scope intentionally narrow and owned by the same domain. This keeps dependencies and responsibility clear, avoids a single "everything depends on this" package, and allows types to evolve with the package they represent.

If we go this route, the guideline could be:

  • No centralized types package.
  • Types should live with their owning package, and only be extracted into a *-types package when there’s a clear consumer need outside that package.
  • Each *-types package should have an explicit scope tied to that domain (e.g., config-related types only).

Makes sense. I've split the types packages into three more specific packages in the latest iteration.

@github-actions github-actions bot added the chore Improvements that don't directly affect features label Feb 11, 2026
Comment on lines +71 to +72
/** @deprecated Use `types` instead */
typings?: string;
Copy link
Member

Choose a reason for hiding this comment

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

We should just remove this.

Suggested change
/** @deprecated Use `types` instead */
typings?: string;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I want to leave it in as it is something that is worth using constraints or package linting to migrate/flag if you have it set.

Copy link
Member

Choose a reason for hiding this comment

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

We can still check whether typings is present in the manifest regardless. We should remove it so that people can't use it.

Comment on lines +54 to +55
"@rnx-kit/types-kit-config": "^0.0.1",
"@rnx-kit/types-node": "^0.0.1"
Copy link
Member

Choose a reason for hiding this comment

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

For dev dependencies, we should use * for now until we figure out a way to use workspace:*

Suggested change
"@rnx-kit/types-kit-config": "^0.0.1",
"@rnx-kit/types-node": "^0.0.1"
"@rnx-kit/types-kit-config": "*",
"@rnx-kit/types-node": "*"

Copy link
Member

Choose a reason for hiding this comment

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

I still don't think it is correct to lump all plugins together like this. It is now too easy for someone to "see patterns" and make them interconnected. We should either keep them within the plugin package, or create separate types packages. I don't believe the number of packages in the repo is going to dominate our CI times.

{
"extends": "@rnx-kit/tsconfig/tsconfig.node.json",
"compilerOptions": {
"emitDeclarationOnly": true
Copy link
Member

Choose a reason for hiding this comment

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

I still don't understand this. If this is a types only package, why do we need to emit anything at all? Can we not just consume the TypeScript?

Comment on lines +71 to +72
/** @deprecated Use `types` instead */
typings?: string;
Copy link
Member

Choose a reason for hiding this comment

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

We can still check whether typings is present in the manifest regardless. We should remove it so that people can't use it.

Copy link
Member

Choose a reason for hiding this comment

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

This should be a separate PR. Let's not scope creep.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore Improvements that don't directly affect features feature: align-deps This is related to align-deps feature: cli This is related to CLI feature: metro This is related to Metro

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants