diff --git a/packages/core/schematics/ng-generate/inject-migration/migration.ts b/packages/core/schematics/ng-generate/inject-migration/migration.ts index 5e0f5b4192a..a21ee7cb501 100644 --- a/packages/core/schematics/ng-generate/inject-migration/migration.ts +++ b/packages/core/schematics/ng-generate/inject-migration/migration.ts @@ -553,14 +553,10 @@ function migrateInjectDecorator( } } } else if ( - // Pass the type for cases like `@Inject(FOO_TOKEN) foo: Foo`, because: - // 1. It guarantees that the type stays the same as before. - // 2. Avoids leaving unused imports behind. - // We only do this for type references since the `@Inject` pattern above is fairly common and - // apps don't necessarily type their injection tokens correctly, whereas doing it for literal - // types will add a lot of noise to the generated code. type && (ts.isTypeReferenceNode(type) || + ts.isTypeLiteralNode(type) || + ts.isTupleTypeNode(type) || (ts.isUnionTypeNode(type) && type.types.some(ts.isTypeReferenceNode))) ) { typeArguments = [type]; diff --git a/packages/core/schematics/test/inject_migration_spec.ts b/packages/core/schematics/test/inject_migration_spec.ts index eba708a1efb..3773e2d1bd8 100644 --- a/packages/core/schematics/test/inject_migration_spec.ts +++ b/packages/core/schematics/test/inject_migration_spec.ts @@ -1282,6 +1282,65 @@ describe('inject migration', () => { ]); }); + it('should preserve type literals in @Inject parameter', async () => { + writeFile( + '/dir.ts', + [ + `import { Directive, Inject } from '@angular/core';`, + `import { FOO_TOKEN } from 'foo';`, + ``, + `@Directive()`, + `class MyDir {`, + ` constructor(@Inject(FOO_TOKEN) private foo: {id: number}) {}`, + `}`, + ].join('\n'), + ); + + await runMigration(); + + expect(tree.readContent('/dir.ts').split('\n')).toEqual([ + `import { Directive, inject } from '@angular/core';`, + `import { FOO_TOKEN } from 'foo';`, + ``, + `@Directive()`, + `class MyDir {`, + ` private foo = inject<{`, + ` id: number;`, + `}>(FOO_TOKEN);`, + `}`, + ]); + }); + + it('should preserve tuple types in @Inject parameter', async () => { + writeFile( + '/dir.ts', + [ + `import { Directive, Inject } from '@angular/core';`, + `import { FOO_TOKEN } from 'foo';`, + ``, + `@Directive()`, + `class MyDir {`, + ` constructor(@Inject(FOO_TOKEN) private foo: [a: number, b: number]) {}`, + `}`, + ].join('\n'), + ); + + await runMigration(); + + expect(tree.readContent('/dir.ts').split('\n')).toEqual([ + `import { Directive, inject } from '@angular/core';`, + `import { FOO_TOKEN } from 'foo';`, + ``, + `@Directive()`, + `class MyDir {`, + ` private foo = inject<[`, + ` a: number,`, + ` b: number`, + `]>(FOO_TOKEN);`, + `}`, + ]); + }); + it('should unwrap forwardRef with an implicit return', async () => { writeFile( '/dir.ts',