@@ -9107,6 +9107,230 @@ function allTests(os: string) {
91079107 // via dynamic imports and an original import can be removed.
91089108 expect ( jsContents ) . not . toContain ( 'import { CmpA }' ) ;
91099109 } ) ;
9110+
9111+ it ( 'should drop imports when one is deferrable and the rest are type-only imports' , ( ) => {
9112+ env . write ( 'cmp-a.ts' , `
9113+ import { Component } from '@angular/core';
9114+
9115+ export class Foo {}
9116+
9117+ @Component({
9118+ standalone: true,
9119+ selector: 'cmp-a',
9120+ template: 'CmpA!'
9121+ })
9122+ export class CmpA {}
9123+ ` ) ;
9124+
9125+ env . write ( '/test.ts' , `
9126+ import { Component } from '@angular/core';
9127+ import { CmpA, type Foo } from './cmp-a';
9128+
9129+ export const foo: Foo = {};
9130+
9131+ @Component({
9132+ selector: 'test-cmp',
9133+ standalone: true,
9134+ imports: [CmpA],
9135+ template: \`
9136+ @defer {
9137+ <cmp-a />
9138+ }
9139+ \`,
9140+ })
9141+ export class TestCmp {}
9142+ ` ) ;
9143+
9144+ env . driveMain ( ) ;
9145+
9146+ const jsContents = env . getContents ( 'test.js' ) ;
9147+
9148+ expect ( jsContents ) . toContain ( 'ɵɵdefer(1, 0, TestCmp_Defer_1_DepsFn)' ) ;
9149+ expect ( jsContents ) . toContain ( '() => [import("./cmp-a").then(m => m.CmpA)]' ) ;
9150+ expect ( jsContents ) . not . toContain ( 'import { CmpA }' ) ;
9151+ } ) ;
9152+
9153+ it ( 'should drop multiple imports to the same file when one is deferrable and the other has a single type-only element' ,
9154+ ( ) => {
9155+ env . write ( 'cmp-a.ts' , `
9156+ import { Component } from '@angular/core';
9157+
9158+ export class Foo {}
9159+
9160+ @Component({
9161+ standalone: true,
9162+ selector: 'cmp-a',
9163+ template: 'CmpA!'
9164+ })
9165+ export class CmpA {}
9166+ ` ) ;
9167+
9168+ env . write ( '/test.ts' , `
9169+ import { Component } from '@angular/core';
9170+ import { CmpA } from './cmp-a';
9171+ import { type Foo } from './cmp-a';
9172+
9173+ export const foo: Foo = {};
9174+
9175+ @Component({
9176+ selector: 'test-cmp',
9177+ standalone: true,
9178+ imports: [CmpA],
9179+ template: \`
9180+ @defer {
9181+ <cmp-a />
9182+ }
9183+ \`,
9184+ })
9185+ export class TestCmp {}
9186+ ` ) ;
9187+
9188+ env . driveMain ( ) ;
9189+
9190+ const jsContents = env . getContents ( 'test.js' ) ;
9191+
9192+ expect ( jsContents ) . toContain ( 'ɵɵdefer(1, 0, TestCmp_Defer_1_DepsFn)' ) ;
9193+ expect ( jsContents ) . toContain ( '() => [import("./cmp-a").then(m => m.CmpA)]' ) ;
9194+ expect ( jsContents ) . not . toContain ( 'import { CmpA }' ) ;
9195+ } ) ;
9196+
9197+ it ( 'should drop multiple imports to the same file when one is deferrable and the other is type-only at the declaration level' ,
9198+ ( ) => {
9199+ env . write ( 'cmp-a.ts' , `
9200+ import { Component } from '@angular/core';
9201+
9202+ export class Foo {}
9203+
9204+ @Component({
9205+ standalone: true,
9206+ selector: 'cmp-a',
9207+ template: 'CmpA!'
9208+ })
9209+ export class CmpA {}
9210+ ` ) ;
9211+
9212+ env . write ( '/test.ts' , `
9213+ import { Component } from '@angular/core';
9214+ import { CmpA } from './cmp-a';
9215+ import type { Foo, CmpA as CmpAlias } from './cmp-a';
9216+
9217+ export const foo: Foo|CmpAlias = {};
9218+
9219+ @Component({
9220+ selector: 'test-cmp',
9221+ standalone: true,
9222+ imports: [CmpA],
9223+ template: \`
9224+ @defer {
9225+ <cmp-a />
9226+ }
9227+ \`,
9228+ })
9229+ export class TestCmp {}
9230+ ` ) ;
9231+
9232+ env . driveMain ( ) ;
9233+
9234+ const jsContents = env . getContents ( 'test.js' ) ;
9235+
9236+ expect ( jsContents ) . toContain ( 'ɵɵdefer(1, 0, TestCmp_Defer_1_DepsFn)' ) ;
9237+ expect ( jsContents ) . toContain ( '() => [import("./cmp-a").then(m => m.CmpA)]' ) ;
9238+ expect ( jsContents ) . not . toContain ( 'import { CmpA }' ) ;
9239+ } ) ;
9240+
9241+ it ( 'should drop multiple imports to the same file when one is deferrable and the other is a type-only import of all symbols' ,
9242+ ( ) => {
9243+ env . write ( 'cmp-a.ts' , `
9244+ import { Component } from '@angular/core';
9245+
9246+ export class Foo {}
9247+
9248+ @Component({
9249+ standalone: true,
9250+ selector: 'cmp-a',
9251+ template: 'CmpA!'
9252+ })
9253+ export class CmpA {}
9254+ ` ) ;
9255+
9256+ env . write ( '/test.ts' , `
9257+ import { Component } from '@angular/core';
9258+ import { CmpA } from './cmp-a';
9259+ import type * as allCmpA from './cmp-a';
9260+
9261+ export const foo: allCmpA.Foo|allCmpA.CmpA = {};
9262+
9263+ @Component({
9264+ selector: 'test-cmp',
9265+ standalone: true,
9266+ imports: [CmpA],
9267+ template: \`
9268+ @defer {
9269+ <cmp-a />
9270+ }
9271+ \`,
9272+ })
9273+ export class TestCmp {}
9274+ ` ) ;
9275+
9276+ env . driveMain ( ) ;
9277+
9278+ const jsContents = env . getContents ( 'test.js' ) ;
9279+
9280+ expect ( jsContents ) . toContain ( 'ɵɵdefer(1, 0, TestCmp_Defer_1_DepsFn)' ) ;
9281+ expect ( jsContents ) . toContain ( '() => [import("./cmp-a").then(m => m.CmpA)]' ) ;
9282+ expect ( jsContents ) . not . toContain ( 'import { CmpA }' ) ;
9283+ } ) ;
9284+
9285+ it ( 'should drop multiple imports of deferrable symbols from the same file' , ( ) => {
9286+ env . write ( 'cmps.ts' , `
9287+ import { Component } from '@angular/core';
9288+
9289+ @Component({
9290+ standalone: true,
9291+ selector: 'cmp-a',
9292+ template: 'CmpA!'
9293+ })
9294+ export class CmpA {}
9295+
9296+ @Component({
9297+ standalone: true,
9298+ selector: 'cmp-b',
9299+ template: 'CmpB!'
9300+ })
9301+ export class CmpB {}
9302+ ` ) ;
9303+
9304+ env . write ( '/test.ts' , `
9305+ import { Component } from '@angular/core';
9306+ import { CmpA } from './cmps';
9307+ import { CmpB } from './cmps';
9308+
9309+ @Component({
9310+ selector: 'test-cmp',
9311+ standalone: true,
9312+ imports: [CmpA, CmpB],
9313+ template: \`
9314+ @defer {
9315+ <cmp-a />
9316+ <cmp-b />
9317+ }
9318+ \`,
9319+ })
9320+ export class TestCmp {}
9321+ ` ) ;
9322+
9323+ env . driveMain ( ) ;
9324+
9325+ const jsContents = env . getContents ( 'test.js' ) ;
9326+
9327+ expect ( jsContents ) . toContain ( 'ɵɵdefer(1, 0, TestCmp_Defer_1_DepsFn)' ) ;
9328+ expect ( jsContents )
9329+ . toContain (
9330+ '() => [import("./cmps").then(m => m.CmpA), import("./cmps").then(m => m.CmpB)]' ) ;
9331+ expect ( jsContents ) . not . toContain ( 'import { CmpA }' ) ;
9332+ expect ( jsContents ) . not . toContain ( 'import { CmpB }' ) ;
9333+ } ) ;
91109334 } ) ;
91119335
91129336 it ( 'should detect pipe used in the `when` trigger as an eager dependency' , ( ) => {
@@ -9327,7 +9551,7 @@ function allTests(os: string) {
93279551 } ) ) ;
93289552 env . write ( `test.ts` , `
93299553 import {Component} from '@angular/core';
9330-
9554+
93319555 @Component({
93329556 template: '...',
93339557 })
@@ -9350,7 +9574,7 @@ function allTests(os: string) {
93509574 } ) ) ;
93519575 env . write ( `test.ts` , `
93529576 import {Component} from '@angular/core';
9353-
9577+
93549578 @Component({
93559579 standalone: true,
93569580 template: '...',
@@ -9368,7 +9592,7 @@ function allTests(os: string) {
93689592 ( ) => {
93699593 env . write ( `test.ts` , `
93709594 import {Component} from '@angular/core';
9371-
9595+
93729596 @Component({
93739597 template: '...',
93749598 })
0 commit comments