diff --git a/packages/compiler/src/core.ts b/packages/compiler/src/core.ts index e34aa4c1c096b5..ff4eb7d4b898b7 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 9ec754f3ab30ac..65e3580881398c 100644 --- a/packages/core/src/application_ref.ts +++ b/packages/core/src/application_ref.ts @@ -477,7 +477,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/injectable.ts b/packages/core/src/di/injectable.ts index d1dacf103318ff..1dd52772b1643c 100644 --- a/packages/core/src/di/injectable.ts +++ b/packages/core/src/di/injectable.ts @@ -8,7 +8,7 @@ import {R3_COMPILE_INJECTABLE} from '../ivy_switch'; import {ReflectionCapabilities} from '../reflection/reflection_capabilities'; -import {Type} from '../type'; +import {Constructor, Type} from '../type'; import {makeDecorator, makeParamDecorator} from '../util/decorators'; import {getClosureSafeProperty} from '../util/property'; @@ -69,7 +69,7 @@ export function convertInjectableProviderToFactory( const reflectionCapabilities = new ReflectionCapabilities(); const deps = reflectionCapabilities.parameters(type); // TODO - convert to flags. - return () => new type(...injectArgs(deps as any[])); + return () => new (type as Constructor)(...injectArgs(deps as any[])); } if (USE_VALUE in provider) { @@ -88,14 +88,14 @@ export function convertInjectableProviderToFactory( const reflectionCapabilities = new ReflectionCapabilities(); deps = reflectionCapabilities.parameters(type); } - return () => new classProvider.useClass(...injectArgs(deps)); + return () => new (classProvider.useClass as Constructor)(...injectArgs(deps)); } else { let deps = (provider as ConstructorSansProvider).deps; if (!deps) { const reflectionCapabilities = new ReflectionCapabilities(); deps = reflectionCapabilities.parameters(type); } - return () => new type(...injectArgs(deps !)); + return () => new (type as Constructor)(...injectArgs(deps !)); } } diff --git a/packages/core/src/di/r3_injector.ts b/packages/core/src/di/r3_injector.ts index e8dcdf42efe988..ed8731133f02d7 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, InjectorDef, InjectorType, InjectorTypeWithProviders} from './defs'; @@ -338,7 +338,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(def.factory); } @@ -360,7 +360,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/component_ref.ts b/packages/core/src/render3/component_ref.ts index 6c1a79c8af0e3e..ebac21d86478a7 100644 --- a/packages/core/src/render3/component_ref.ts +++ b/packages/core/src/render3/component_ref.ts @@ -21,7 +21,7 @@ import {LifecycleHooksFeature, createRootContext} from './component'; import {baseDirectiveCreate, createLNode, createLViewData, createTView, elementCreate, enterView, hostElement, initChangeDetectorIfExisting, locateHostElement, renderEmbeddedTemplate} from './instructions'; import {ComponentDefInternal, ComponentType, RenderFlags} from './interfaces/definition'; import {LElementNode, TNode, TNodeType} from './interfaces/node'; -import {RElement, domRendererFactory3} from './interfaces/renderer'; +import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer'; import {CONTEXT, FLAGS, INJECTOR, LViewData, LViewFlags, RootContext, TVIEW} from './interfaces/view'; import {RootViewRef, ViewRef} from './view_ref'; @@ -84,8 +84,9 @@ export class ComponentFactory extends viewEngine_ComponentFactory { ngModule?: viewEngine_NgModuleRef|undefined): viewEngine_ComponentRef { const isInternalRootView = rootSelectorOrNode === undefined; + // Cannot call method of union type: https://github.com/Microsoft/TypeScript/issues/7294 const rendererFactory = - ngModule ? ngModule.injector.get(RendererFactory2) : domRendererFactory3; + ngModule ? ngModule.injector.get(RendererFactory2) : domRendererFactory3; const hostNode = isInternalRootView ? elementCreate( this.selector, rendererFactory.createRenderer(null, this.componentDef.rendererType)) : diff --git a/packages/core/src/render3/definition.ts b/packages/core/src/render3/definition.ts index 0de1e46439c868..e30ed483532b5c 100644 --- a/packages/core/src/render3/definition.ts +++ b/packages/core/src/render3/definition.ts @@ -232,13 +232,13 @@ export function defineComponent(componentDefinition: { outputs: invertObject(componentDefinition.outputs), rendererType: resolveRendererType2(componentDefinition.rendererType) || null, 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) @@ -505,6 +505,6 @@ 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 afc631d7c9ee6c..a8b3807f73c719 100644 --- a/packages/core/test/render3/compiler_canonical/small_app_spec.ts +++ b/packages/core/test/render3/compiler_canonical/small_app_spec.ts @@ -97,7 +97,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({