Skip to content

feat: generate .d.ts Ivy type declarations for Angular library builds#101

Merged
Brooooooklyn merged 4 commits intomainfrom
feat/dts-declarations
Mar 10, 2026
Merged

feat: generate .d.ts Ivy type declarations for Angular library builds#101
Brooooooklyn merged 4 commits intomainfrom
feat/dts-declarations

Conversation

@Brooooooklyn
Copy link
Member

@Brooooooklyn Brooooooklyn commented Mar 10, 2026

feat: generate .d.ts Ivy type declarations for Angular library builds

Add dts_declarations field to TransformResult that generates the static
type declarations (ɵfac, ɵcmp, ɵdir, ɵpipe, ɵmod, ɵinj, ɵprov) needed in
.d.ts files for Angular library consumers to perform template type-checking.

This enables build tools like tsdown to post-process .d.ts output and inject
Ivy declarations, solving the "Component imports must be standalone" error when
publishing Angular libraries compiled with Oxc.

Supports all Angular decorator types: @component, @directive, @pipe, @NgModule,
and @Injectable, including input/output maps, signal inputs, exportAs, host
directives, and constructor @Attribute() dependencies.

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

fix: align .d.ts declarations with Angular TS compiler

  • Fix factory CtorDeps to emit object literal types with attribute/optional/host/self/skipSelf
  • Emit null instead of "" for pipe names when not specified
  • Add type_argument_count support for generic Injectable/Pipe/NgModule
  • Handle control character escaping (\n, \r, \t) in dts strings
  • Surface ng-content selectors from template compilation pipeline
  • Generate ngAcceptInputType_* fields for inputs with transforms
  • Add comprehensive tests for all dts generation scenarios

Fix #86

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com


Note

Medium Risk
Adds a new public API field (dts_declarations) and substantial new declaration-generation logic that runs during transforms; while mostly additive, it could impact downstream Rust/NAPI consumers and edge cases in metadata extraction.

Overview
Adds .d.ts Ivy declaration generation for Angular library builds by introducing TransformResult.dts_declarations and a new dts module that emits static type members for @Component, @Directive, @Pipe, @NgModule, and @Injectable (including inputs/outputs, queries, host directives, ctor dep flags, generics-as-any, and ngAcceptInputType_* for transformed inputs).

Updates the component compilation pipeline to capture ng-content selectors and query property names needed for declaration typing, and surfaces the new data through the NAPI bindings/TypeScript typings. Adds extensive integration tests covering the supported .d.ts scenarios.

Written by Cursor Bugbot for commit aa589b7. This will update automatically on new commits. Configure here.

Brooooooklyn and others added 2 commits March 10, 2026 11:33
Add `dts_declarations` field to `TransformResult` that generates the static
type declarations (ɵfac, ɵcmp, ɵdir, ɵpipe, ɵmod, ɵinj, ɵprov) needed in
`.d.ts` files for Angular library consumers to perform template type-checking.

This enables build tools like tsdown to post-process `.d.ts` output and inject
Ivy declarations, solving the "Component imports must be standalone" error when
publishing Angular libraries compiled with Oxc.

Supports all Angular decorator types: @component, @directive, @pipe, @NgModule,
and @Injectable, including input/output maps, signal inputs, exportAs, host
directives, and constructor @Attribute() dependencies.

- Close #86

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix factory CtorDeps to emit object literal types with attribute/optional/host/self/skipSelf
- Emit `null` instead of `""` for pipe names when not specified
- Add type_argument_count support for generic Injectable/Pipe/NgModule
- Handle control character escaping (\n, \r, \t) in dts strings
- Surface ng-content selectors from template compilation pipeline
- Generate ngAcceptInputType_* fields for inputs with transforms
- Add comprehensive tests for all dts generation scenarios

Fix #86

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

… deps

- Handle ReadProp (namespace-qualified, e.g. i1.SomeDirective) and
  External expression variants in extract_directive_name_from_expr
- Replace silent "unknown" fallback with descriptive panic for
  unhandled variants
- Extract shared ctor deps formatting logic into generate_ctor_deps_type
  helper, reducing ~80 lines of duplication

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

…xtract_injectable_metadata calls

- Set type_argument_count on directive metadata from class.type_parameters,
  matching how Component/Pipe/NgModule/Injectable already do it.
  Without this, generic directives like `MyDirective<T>` emit `MyDirective`
  instead of `MyDirective<any>` in .d.ts declarations.
- Eliminate 4 redundant extract_injectable_metadata calls (one per decorator
  branch) by capturing the result of the first call and deriving the boolean.
- Add test for generic directive dts output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Brooooooklyn
Copy link
Member Author

@codex review

@Brooooooklyn Brooooooklyn merged commit 3e84e1c into main Mar 10, 2026
4 checks passed
@Brooooooklyn Brooooooklyn deleted the feat/dts-declarations branch March 10, 2026 07:52
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aa589b7b04

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

metadata
.imports
.iter()
.map(|i| format!("typeof {}", i.as_str()))

Choose a reason for hiding this comment

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

P1 Badge Emit importable refs for NgModule d.ts tuple types

The generate_ng_module_dts output uses raw typeof <identifier> entries for declarations/imports/exports, but TransformResult only exposes member text and no import metadata. In declaration-only builds, TypeScript commonly elides imports that are used only inside @NgModule(...), so after injecting this member, symbols like CommonModule are out of scope and consumers hit Cannot find name errors from the published .d.ts.

Useful? React with 👍 / 👎.

let entries: Vec<String> = host_directives
.iter()
.map(|hd| {
let directive = format!("typeof {}", hd.directive.as_str());

Choose a reason for hiding this comment

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

P1 Badge Include hostDirective import data in d.ts output

Host directive typing is emitted as typeof <directive> using only the symbol text, but this API does not return the module path/imports needed to make those symbols resolvable in the target .d.ts. Because host directives are typically referenced only in decorator metadata, their imports are often absent in emitted declarations, so injecting these members can leave unresolved directive names or alias mismatches.

Useful? React with 👍 / 👎.

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.

Library build support: missing ɵcmp ivy declarations in .d.ts output

1 participant