Skip to content

fix(types): make templateParams extensible via module augmentation#679

Merged
harlan-zw merged 2 commits into
mainfrom
fix/575-augment-module-types
Mar 10, 2026
Merged

fix(types): make templateParams extensible via module augmentation#679
harlan-zw merged 2 commits into
mainfrom
fix/575-augment-module-types

Conversation

@harlan-zw

@harlan-zw harlan-zw commented Mar 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds templateParams to SchemaAugmentations interface so users can extend it via module augmentation
  • Updates Vue's ReactiveHead.templateParams to use the shared ResolvableTemplateParams type

Users can now do:

declare module 'unhead/types' {
  interface SchemaAugmentations {
    templateParams: { siteName: string; foo?: string }
  }
}

Closes #575

Summary by CodeRabbit

  • Refactor
    • Standardized template-parameter typing across packages to improve type consistency and cross-package resolution.
    • Exposed augmentation support for template parameters to allow safer, extensible typing across integrations.

Add `templateParams` to `SchemaAugmentations` and intersect it into
`ResolvableTemplateParams`, allowing users to extend templateParams
via `declare module 'unhead/types' { interface SchemaAugmentations { templateParams: { foo: string } } }`.
Also updates `ReactiveHead.templateParams` in the Vue package to use
the shared `ResolvableTemplateParams` type.

Closes #575
@coderabbitai

coderabbitai Bot commented Mar 10, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a public augmentation interface for template parameters in unhead and updates the Vue package's ReactiveHead.templateParams type to reference the centralized ResolvableTemplateParams, aligning cross-package types for module augmentation.

Changes

Cohort / File(s) Summary
Unhead types
packages/unhead/src/types/schema/head.ts
Exported a new public augmentation interface (TemplateParamsAugmentations) and extended ResolvableTemplateParams to intersect with that augmentation, enabling module augmentation for template params.
Vue types
packages/vue/src/types/schema.ts
Replaced inline templateParams type with ResolvableProperties<ResolvableTemplateParams> and added the ResolvableTemplateParams import from unhead to align types.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I nibble lines of types with care,
A tiny key for params to share.
Augments unfurl, the types take flight,
Small hops, big safety — what a sight! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: making templateParams extensible via module augmentation, which matches the primary objective of the PR.
Description check ✅ Passed The PR description provides a clear summary of changes, includes the rationale, and provides a usage example. However, the description template requires checking type of change, which is not explicitly marked.
Linked Issues check ✅ Passed The PR successfully addresses issue #575 by introducing ResolvableTemplateParams type and enabling module augmentation of templateParams through SchemaAugmentations interface, exactly as requested.
Out of Scope Changes check ✅ Passed All changes are within scope: adding TemplateParamsAugmentations interface, updating ResolvableTemplateParams, and aligning Vue's ReactiveHead.templateParams type are all directly related to the objective of making templateParams extensible.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/575-augment-module-types

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown
Contributor

Bundle Size Analysis

Bundle Size Gzipped
Client (Minimal) 10.5 kB 4.3 kB
Server (Minimal) 10.2 kB 4.2 kB
Vue Client (Minimal) 11.4 kB 4.7 kB
Vue Server (Minimal) 11.1 kB 4.6 kB

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/unhead/src/types/schema/head.ts (1)

74-86: ⚠️ Potential issue | 🟠 Major

TypeScript will reject the documented augmentation pattern due to type incompatibility.

Declaring templateParams: object in SchemaAugmentations prevents consumers from augmenting it with a narrower type like { siteName: string }. TypeScript's declaration merging rule requires non-function members to have identical types—this pattern will fail with TS2717: "Subsequent property declarations must have the same type".

Create a dedicated empty interface for template parameter augmentation and intersect it into both SchemaAugmentations and ResolvableTemplateParams instead. This allows consumers to extend the shape without conflicting with an existing property type.

Suggested direction
+export interface TemplateParamsAugmentations {}
+
 export interface SchemaAugmentations {
   title: TagPriority
   titleTemplate: TagPriority
   base: ResolvesDuplicates & TagPriority
   htmlAttrs: ResolvesDuplicates & TagPriority
   bodyAttrs: ResolvesDuplicates & TagPriority
   link: TagPriority & TagPosition & ResolvesDuplicates & ProcessesTemplateParams
   meta: TagPriority & ResolvesDuplicates & ProcessesTemplateParams
   style: TagPriority & TagPosition & StringInnerContent & ResolvesDuplicates & ProcessesTemplateParams
   script: TagPriority & TagPosition & InnerContent & ResolvesDuplicates & ProcessesTemplateParams
   noscript: TagPriority & TagPosition & StringInnerContent & ResolvesDuplicates & ProcessesTemplateParams
-  templateParams: object
+  templateParams: TemplateParamsAugmentations
 }
…
-export type ResolvableTemplateParams = { separator?: '|' | '-' | '·' | string } & Record<string, null | string | Record<string, string>> & SchemaAugmentations['templateParams']
+export type ResolvableTemplateParams =
+  { separator?: '|' | '-' | '·' | string }
+  & Record<string, null | string | Record<string, string>>
+  & TemplateParamsAugmentations

Consumers then augment TemplateParamsAugmentations directly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/unhead/src/types/schema/head.ts` around lines 74 - 86, Replace the
concrete property "templateParams: object" on SchemaAugmentations with a
dedicated empty augmentation interface and intersect it where needed: add an
empty exported interface TemplateParamsAugmentations {}, remove the
templateParams: object declaration from SchemaAugmentations and instead
intersect TemplateParamsAugmentations into SchemaAugmentations and into
ResolvableTemplateParams (so both types include the augmentable shape). This
lets consumers extend TemplateParamsAugmentations (e.g. declare module ...
interface TemplateParamsAugmentations { siteName: string }) without triggering
TS2717 while preserving existing behavior in SchemaAugmentations and
ResolvableTemplateParams.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/unhead/src/types/schema/head.ts`:
- Around line 74-86: Replace the concrete property "templateParams: object" on
SchemaAugmentations with a dedicated empty augmentation interface and intersect
it where needed: add an empty exported interface TemplateParamsAugmentations {},
remove the templateParams: object declaration from SchemaAugmentations and
instead intersect TemplateParamsAugmentations into SchemaAugmentations and into
ResolvableTemplateParams (so both types include the augmentable shape). This
lets consumers extend TemplateParamsAugmentations (e.g. declare module ...
interface TemplateParamsAugmentations { siteName: string }) without triggering
TS2717 while preserving existing behavior in SchemaAugmentations and
ResolvableTemplateParams.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3bff878c-cf07-4266-92f5-78884f306594

📥 Commits

Reviewing files that changed from the base of the PR and between 4838b84 and ef3df72.

📒 Files selected for processing (2)
  • packages/unhead/src/types/schema/head.ts
  • packages/vue/src/types/schema.ts

@harlan-zw

Copy link
Copy Markdown
Collaborator Author

@copilot can you address code rabbit's issue

Copilot AI commented Mar 10, 2026

Copy link
Copy Markdown
Contributor

@harlan-zw I've opened a new pull request, #684, to work on those changes. Once the pull request is ready, I'll request review from you.

)

* Initial plan

* fix(types): use dedicated TemplateParamsAugmentations interface to avoid TS2717

Co-authored-by: harlan-zw <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: harlan-zw <[email protected]>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/unhead/src/types/schema/head.ts (1)

74-75: Consider adding JSDoc to clarify augmentation usage.

The empty interface is intentional and correct for TypeScript module augmentation—Biome's warning can be safely ignored here. Adding a brief JSDoc comment would help consumers understand how to extend this interface:

📝 Suggested documentation
+/**
+ * Augment this interface to add custom template parameter types.
+ * `@example`
+ * declare module 'unhead/types' {
+ *   interface TemplateParamsAugmentations {
+ *     siteName: string
+ *     foo?: string
+ *   }
+ * }
+ */
 export interface TemplateParamsAugmentations {}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/unhead/src/types/schema/head.ts` around lines 74 - 75, Add a concise
JSDoc comment above the empty interface TemplateParamsAugmentations explaining
that the interface is intentionally empty and provided for TypeScript module
augmentation (i.e., consumers should declare module augmentation to extend it),
note that tooling warnings (Biome) can be ignored, and include a brief one-line
example description of how to extend it so readers know the intended usage and
purpose.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/unhead/src/types/schema/head.ts`:
- Around line 74-75: Add a concise JSDoc comment above the empty interface
TemplateParamsAugmentations explaining that the interface is intentionally empty
and provided for TypeScript module augmentation (i.e., consumers should declare
module augmentation to extend it), note that tooling warnings (Biome) can be
ignored, and include a brief one-line example description of how to extend it so
readers know the intended usage and purpose.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6dd6599b-c1bd-488f-aa4f-42b94617e5b6

📥 Commits

Reviewing files that changed from the base of the PR and between ef3df72 and 1ec203c.

📒 Files selected for processing (1)
  • packages/unhead/src/types/schema/head.ts

@harlan-zw harlan-zw merged commit b062715 into main Mar 10, 2026
6 checks passed
@harlan-zw harlan-zw mentioned this pull request Apr 4, 2026
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.

Augment module types

2 participants