Skip to content

fix(queries): compile decorator queries: and match ngtsc's query options - #495

Open
ashley-hunter wants to merge 1 commit into
feat/validate-input-transformsfrom
feat/decorator-metadata-queries
Open

ashley-hunter wants to merge 1 commit into
feat/validate-input-transformsfrom
feat/decorator-metadata-queries

Conversation

@ashley-hunter

@ashley-hunter ashley-hunter commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Stack (3/4): #493 inputs/outputs → #494 transform validation → #495 queries: → #496 .d.ts transform types. This is #495.

Compiles queries: declared in @Directive / @Component metadata, and matches ngtsc on a few member-query options.

The bug

@Directive({ selector: '[d]', queries: { el: new ViewChild('el') } })
export class D { el!: ElementRef; }

compiled with no view query, so el was never set. The queries key was ignored like inputs: was.

The fix

queries: is parsed like ngtsc's extractQueriesFromDecorator: new ViewChild/ViewChildren/ContentChild/ContentChildren(...) imported from @angular/core (directly or through a namespace import), appended after the member queries. It raises ngtsc's diagnostics word for word:

  • not an object literal
  • not a query type
  • missing or extra arguments
  • non-object options
  • a non-boolean descendants, static or emitDistinctChangesOnly
  • predicates that can't be interpreted
  • a signal query for the same property

Member query decorators now also match ngtsc:

  • @ViewChild/@ViewChildren honour descendants and emitDistinctChangesOnly. They were hard-coded before, so this changes the emitted query flags for code that sets them.
  • A predicate referencing a same-file string const (@ViewChild(SELECTOR)) compiles to that selector instead of a type predicate.
  • forwardRef(function () { return X; }), and forwardRef behind parentheses or as, is unwrapped like the arrow form.

extract_class_queries returns a class's queries as they're compiled. The compiler and the NAPI extractComponentMetadataSync both use it, so the metadata API now reports the same queries.

Tests

Added to the ngtsc snapshot: Angular's queries specs (ngtsc_spec's decorator-queries errors and "should generate queries for components/directives", forwardRef, and the authoring_queries_spec collisions), plus probes of every error, the flags and the ordering. A new NAPI test covers extractComponentMetadataSync, and it failed before the fix.

…tions

`@Directive({ queries: { el: new ViewChild('el') } })` (and `@Component`) was
ignored, so those queries never ran. It's now parsed like ngtsc's
`extractQueriesFromDecorator`: `new ViewChild/ViewChildren/ContentChild/
ContentChildren(...)` imported from `@angular/core` (directly or through a
namespace import), appended after the member queries, with ngtsc's diagnostics
word for word (not an object literal, not a query type, missing/extra
arguments, non-object options, non-boolean `descendants`/`static`/
`emitDistinctChangesOnly`, uninterpretable predicates, and a signal query
declared for the same property).

Member query decorators now match ngtsc too:

- `descendants` and `emitDistinctChangesOnly` are honoured on `@ViewChild`/
  `@ViewChildren` (they were hard-coded), which changes the emitted flags
- a predicate referencing a same-file string const (`@ViewChild(SELECTOR)`)
  compiles to that selector rather than to a type predicate
- `forwardRef(function () { return X; })`, and `forwardRef` behind parentheses
  or `as`, is unwrapped like the arrow form

`extract_class_queries` returns a class's queries as they're compiled; the
compiler and the NAPI `extractComponentMetadataSync` both use it, so the
metadata API reports the same queries.
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.

1 participant