diff --git a/packages/compiler-cli/integrationtest/bazel/injectable_def/app/src/dep.ts b/packages/compiler-cli/integrationtest/bazel/injectable_def/app/src/dep.ts index 4cc1c02b7d9850..824209cd51131a 100644 --- a/packages/compiler-cli/integrationtest/bazel/injectable_def/app/src/dep.ts +++ b/packages/compiler-cli/integrationtest/bazel/injectable_def/app/src/dep.ts @@ -38,4 +38,4 @@ export class DepAppModule { @Injectable({providedIn: DepAppModule}) export class ShakeableService { constructor(readonly normal: NormalService) {} -} \ No newline at end of file +} diff --git a/packages/compiler-cli/integrationtest/bazel/injectable_def/app/src/token.ts b/packages/compiler-cli/integrationtest/bazel/injectable_def/app/src/token.ts index 3b93c3e5d8591a..8ab8183510965f 100644 --- a/packages/compiler-cli/integrationtest/bazel/injectable_def/app/src/token.ts +++ b/packages/compiler-cli/integrationtest/bazel/injectable_def/app/src/token.ts @@ -18,7 +18,7 @@ export class TokenModule { export const TOKEN = new InjectionToken('test', { providedIn: TokenModule, - factory: () => new Service(inject(Dep)), + factory: () => new Service(inject(Dep), inject(AbstractDep)), }); @@ -49,6 +49,11 @@ export class Dep { readonly data = 'fromToken'; } +@Injectable({providedIn: 'root', useValue: {value: 42}}) +export abstract class AbstractDep { + abstract value: number; +} + export class Service { - constructor(readonly dep: Dep) {} + constructor(readonly dep: Dep, unused: AbstractDep) {} } diff --git a/packages/compiler/src/core.ts b/packages/compiler/src/core.ts index 58577c90391905..3eebe3cc2d510f 100644 --- a/packages/compiler/src/core.ts +++ b/packages/compiler/src/core.ts @@ -154,7 +154,8 @@ export const createSelf = makeMetadataFactory('Self'); export const createSkipSelf = makeMetadataFactory('SkipSelf'); export const createHost = makeMetadataFactory('Host'); -export interface Type extends Function { new (...args: any[]): any; } +export interface Type extends Function { prototype: any; } + export const Type = Function; export enum SecurityContext { diff --git a/packages/core/src/application_ref.ts b/packages/core/src/application_ref.ts index c6979b8a034297..3aa99a7a2dc92f 100644 --- a/packages/core/src/application_ref.ts +++ b/packages/core/src/application_ref.ts @@ -465,7 +465,7 @@ export class ApplicationRef { // Create a factory associated with the current module if it's not bound to some other const ngModule = componentFactory instanceof ComponentFactoryBoundToModule ? - null : + undefined : this._injector.get(NgModuleRef); const selectorOrNode = rootSelectorOrNode || componentFactory.selector; const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule); diff --git a/packages/core/src/di/r3_injector.ts b/packages/core/src/di/r3_injector.ts index 5d6395b4494072..ae9c16f1ec9abf 100644 --- a/packages/core/src/di/r3_injector.ts +++ b/packages/core/src/di/r3_injector.ts @@ -7,7 +7,7 @@ */ import {OnDestroy} from '../metadata/lifecycle_hooks'; -import {Type} from '../type'; +import {Constructor, Type} from '../type'; import {stringify} from '../util'; import {InjectableDef, InjectableType, InjectorType, InjectorTypeWithProviders, getInjectableDef, getInjectorDef} from './defs'; @@ -336,7 +336,7 @@ function injectableDefRecord(token: Type| InjectionToken): Record } // TODO(alxhub): there should probably be a strict mode which throws here instead of assuming a // no-args constructor. - return makeRecord(() => new (token as Type)()); + return makeRecord(() => new (token as Constructor)()); } return makeRecord(injectableDef.factory); } @@ -358,7 +358,7 @@ function providerToRecord(provider: SingleProvider): Record { } else { const classRef = (provider as StaticClassProvider | ClassProvider).useClass || token; if (hasDeps(provider)) { - factory = () => new (classRef)(...injectArgs(provider.deps)); + factory = () => new (classRef as Constructor)(...injectArgs(provider.deps)); } else { return injectableDefRecord(classRef); } diff --git a/packages/core/src/reflection/reflection_capabilities.ts b/packages/core/src/reflection/reflection_capabilities.ts index 57e58c2f18e2b3..9daedcc1ea0ed8 100644 --- a/packages/core/src/reflection/reflection_capabilities.ts +++ b/packages/core/src/reflection/reflection_capabilities.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {Type, isType} from '../type'; +import {Constructor, Type, isType} from '../type'; import {global, stringify} from '../util'; import {ANNOTATIONS, PARAMETERS, PROP_METADATA} from '../util/decorators'; @@ -29,7 +29,7 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities { isReflectionEnabled(): boolean { return true; } - factory(t: Type): (args: any[]) => T { return (...args: any[]) => new t(...args); } + factory(t: Constructor): (args: any[]) => T { return (...args: any[]) => new t(...args); } /** @internal */ _zipTypesAndAnnotations(paramTypes: any[], paramAnnotations: any[]): any[][] { diff --git a/packages/core/src/render3/definition.ts b/packages/core/src/render3/definition.ts index 2969c44b2a291f..692a5019c1276e 100644 --- a/packages/core/src/render3/definition.ts +++ b/packages/core/src/render3/definition.ts @@ -296,13 +296,13 @@ export function defineComponent(componentDefinition: { declaredInputs: declaredInputs, outputs: invertObject(componentDefinition.outputs), exportAs: componentDefinition.exportAs || null, - onInit: type.prototype.ngOnInit || null, - doCheck: type.prototype.ngDoCheck || null, - afterContentInit: type.prototype.ngAfterContentInit || null, - afterContentChecked: type.prototype.ngAfterContentChecked || null, - afterViewInit: type.prototype.ngAfterViewInit || null, - afterViewChecked: type.prototype.ngAfterViewChecked || null, - onDestroy: type.prototype.ngOnDestroy || null, + onInit: (type.prototype as any).ngOnInit || null, + doCheck: (type.prototype as any).ngDoCheck || null, + afterContentInit: (type.prototype as any).ngAfterContentInit || null, + afterContentChecked: (type.prototype as any).ngAfterContentChecked || null, + afterViewInit: (type.prototype as any).ngAfterViewInit || null, + afterViewChecked: (type.prototype as any).ngAfterViewChecked || null, + onDestroy: (type.prototype as any).ngOnDestroy || null, onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush, directiveDefs: directiveTypes ? () => (typeof directiveTypes === 'function' ? directiveTypes() : directiveTypes) @@ -660,7 +660,7 @@ export function definePipe(pipeDef: { name: pipeDef.name, factory: pipeDef.factory, pure: pipeDef.pure !== false, - onDestroy: pipeDef.type.prototype.ngOnDestroy || null + onDestroy: (pipeDef.type.prototype as any).ngOnDestroy || null }) as never; } diff --git a/packages/core/src/type.ts b/packages/core/src/type.ts index 42f072385bdff5..bc1f71e82d82a6 100644 --- a/packages/core/src/type.ts +++ b/packages/core/src/type.ts @@ -22,4 +22,6 @@ export function isType(v: any): v is Type { return typeof v === 'function'; } -export interface Type extends Function { new (...args: any[]): T; } +export interface Type extends Function { prototype: T; } + +export interface Constructor extends Type { new (...args: any[]): T; } diff --git a/packages/core/test/render3/compiler_canonical/small_app_spec.ts b/packages/core/test/render3/compiler_canonical/small_app_spec.ts index 621203368a1aef..b8c05e8595c7bd 100644 --- a/packages/core/test/render3/compiler_canonical/small_app_spec.ts +++ b/packages/core/test/render3/compiler_canonical/small_app_spec.ts @@ -101,7 +101,8 @@ class ToDoAppComponent { // NON-NORMATIVE (ToDoAppComponent.ngComponentDef as r3.ComponentDefInternal).directiveDefs = () => - [ToDoItemComponent.ngComponentDef, (NgForOf as r3.DirectiveType>).ngDirectiveDef]; + [ToDoItemComponent.ngComponentDef, + (NgForOf as any as r3.DirectiveType>).ngDirectiveDef]; // /NON-NORMATIVE @Component({