Skip to content

Commit 7e03af8

Browse files
crisbetoalxhub
authored andcommitted
fix(compiler-cli): set correct target when type checking events (#60561)
Currently the TCB generation code doesn't handle targeted events (e.g. `(document:click)`) which ends up binding to the current element and can have type inference implications. These changes take the event's `target` into account. PR Close #60561
1 parent ec8c8f8 commit 7e03af8

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

packages/compiler-cli/src/ngtsc/typecheck/src/type_check_block.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,11 +1578,19 @@ class TcbUnclaimedOutputsOp extends TcbOp {
15781578
// `$event` depending on the event name. For unknown event names, TypeScript resorts to the
15791579
// base `Event` type.
15801580
const handler = tcbCreateEventHandler(output, this.tcb, this.scope, EventParamType.Infer);
1581-
1582-
if (elId === null) {
1583-
elId = this.scope.resolve(this.target);
1581+
let target: ts.Expression;
1582+
// Only check for `window` and `document` since in theory any target can be passed.
1583+
if (output.target === 'window' || output.target === 'document') {
1584+
target = ts.factory.createIdentifier(output.target);
1585+
} else if (elId === null) {
1586+
target = elId = this.scope.resolve(this.target);
1587+
} else {
1588+
target = elId;
15841589
}
1585-
const propertyAccess = ts.factory.createPropertyAccessExpression(elId, 'addEventListener');
1590+
const propertyAccess = ts.factory.createPropertyAccessExpression(
1591+
target,
1592+
'addEventListener',
1593+
);
15861594
addParseSpanInfo(propertyAccess, output.keySpan);
15871595
const call = ts.factory.createCallExpression(
15881596
/* expression */ propertyAccess,

packages/compiler-cli/src/ngtsc/typecheck/test/type_check_block_spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,20 @@ describe('type check blocks', () => {
357357
);
358358
});
359359

360+
it('should generate code for event targeting `window`', () => {
361+
const block = tcb(`<button (window:scroll)="handle()"></button>`);
362+
expect(block).toContain(
363+
'window.addEventListener("scroll", ($event): any => { (this).handle(); });',
364+
);
365+
});
366+
367+
it('should generate code for event targeting `document`', () => {
368+
const block = tcb(`<button (document:click)="handle()"></button>`);
369+
expect(block).toContain(
370+
'document.addEventListener("click", ($event): any => { (this).handle(); });',
371+
);
372+
});
373+
360374
it('should only generate directive declarations that have bindings or are referenced', () => {
361375
const TEMPLATE = `
362376
<div

0 commit comments

Comments
 (0)