ngtsc treats an empty component selector like a missing one and uses ng-component. OXC keeps '', both in the runtime selectors and in .d.ts.
Repro
import {Component} from '@angular/core';
@Component({selector: '', template: ''})
export class C {}
OXC (main and #504 tip)
static ɵcmp = i0.ɵɵdefineComponent({type:C,selectors:[],decls:0,vars:0, ...
static ɵcmp: i0.ɵɵComponentDeclaration<C, "", never, {}, {}, never, never, true, never>;
ngtsc 22.1.7
static ɵcmp = i0.ɵɵdefineComponent({ type: C, selectors: [["ng-component"]], decls: 0, vars: 0, ...
static ɵcmp: i0.ɵɵComponentDeclaration<C, "ng-component", never, {}, {}, never, never, true, never>;
This matters at runtime. When a component is created without a host element (router outlet, createComponent), the host tag name comes from inferTagNameFromDefinition in packages/core/src/render3/component_ref.ts, which reads componentDef.selectors[0][0]. With selectors: [] that reads a property of undefined. Not tested at runtime, based on reading the code.
State in the stack
The stack already handles a missing selector: @Component({template: ''}) gives "ng-component" in .d.ts at the #504 tip (main printed never). The JS was already [["ng-component"]] on main. Only the empty-string case is still wrong.
Where
Selector handling in crates/oxc_angular_compiler/src/component/decorator.rs (and the .d.ts selector in dts.rs). In ngtsc, extractDirectiveMetadata (annotations/directive/src/shared.ts L287) does selector = resolved === '' ? defaultSelector : resolved;. For components defaultSelector is 'ng-component'. For directives it is null, which leads to NG2004, tracked in the diagnostics issue.
On main?
Yes.
ngtsc treats an empty component selector like a missing one and uses
ng-component. OXC keeps'', both in the runtime selectors and in.d.ts.Repro
OXC (main and #504 tip)
ngtsc 22.1.7
This matters at runtime. When a component is created without a host element (router outlet,
createComponent), the host tag name comes frominferTagNameFromDefinitioninpackages/core/src/render3/component_ref.ts, which readscomponentDef.selectors[0][0]. Withselectors: []that reads a property ofundefined. Not tested at runtime, based on reading the code.State in the stack
The stack already handles a missing
selector:@Component({template: ''})gives"ng-component"in.d.tsat the #504 tip (main printednever). The JS was already[["ng-component"]]on main. Only the empty-string case is still wrong.Where
Selector handling in
crates/oxc_angular_compiler/src/component/decorator.rs(and the.d.tsselector indts.rs). In ngtsc,extractDirectiveMetadata(annotations/directive/src/shared.tsL287) doesselector = resolved === '' ? defaultSelector : resolved;. For componentsdefaultSelectoris'ng-component'. For directives it isnull, which leads to NG2004, tracked in the diagnostics issue.On main?
Yes.