diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/directive.ts b/packages/compiler-cli/src/ngtsc/annotations/src/directive.ts index ce32ab2feb..e67d5bce2b 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/src/directive.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/src/directive.ts @@ -156,7 +156,7 @@ export function extractDirectiveMetadata( inputs: {...inputsFromMeta, ...inputsFromFields}, outputs: {...outputsFromMeta, ...outputsFromFields}, queries, selector, type: new WrappedNodeExpr(clazz.name !), - typeArgumentCount: (clazz.typeParameters || []).length, + typeArgumentCount: reflector.getGenericArityOfClass(clazz) || 0, typeSourceSpan: null !, usesInheritance, exportAs, }; return {decoratedElements, decorator: directive, metadata}; diff --git a/packages/compiler-cli/src/ngtsc/host/src/reflection.ts b/packages/compiler-cli/src/ngtsc/host/src/reflection.ts index 21f4efede4..bb205a125d 100644 --- a/packages/compiler-cli/src/ngtsc/host/src/reflection.ts +++ b/packages/compiler-cli/src/ngtsc/host/src/reflection.ts @@ -411,4 +411,12 @@ export interface ReflectionHost { isClass(node: ts.Node): boolean; hasBaseClass(node: ts.Declaration): boolean; + + /** + * Get the number of generic type parameters of a given class. + * + * @returns the number of type parameters of the class, if known, or `null` if the declaration + * is not a class or has an unknown number of type parameters. + */ + getGenericArityOfClass(clazz: ts.Declaration): number|null; } diff --git a/packages/compiler-cli/src/ngtsc/metadata/src/reflector.ts b/packages/compiler-cli/src/ngtsc/metadata/src/reflector.ts index 608dde3c3a..d03bdbd26e 100644 --- a/packages/compiler-cli/src/ngtsc/metadata/src/reflector.ts +++ b/packages/compiler-cli/src/ngtsc/metadata/src/reflector.ts @@ -159,6 +159,13 @@ export class TypeScriptReflectionHost implements ReflectionHost { }; } + getGenericArityOfClass(clazz: ts.Declaration): number|null { + if (!ts.isClassDeclaration(clazz)) { + return null; + } + return clazz.typeParameters !== undefined ? clazz.typeParameters.length : 0; + } + /** * Resolve a `ts.Symbol` to its declaration, keeping track of the `viaModule` along the way. * diff --git a/packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts b/packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts index c3808a60d9..a0988a5e37 100644 --- a/packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts +++ b/packages/compiler-cli/src/ngtsc/metadata/src/resolver.ts @@ -17,7 +17,7 @@ import * as ts from 'typescript'; import {ClassMemberKind, ReflectionHost} from '../../host'; -const TS_DTS_EXTENSION = /(\.d)?\.ts$/; +const TS_DTS_JS_EXTENSION = /(\.d)?\.ts|\.js$/; /** * Represents a value which cannot be determined statically. @@ -147,7 +147,7 @@ export class ResolvedReference extends Reference // TODO(alxhub): investigate the need to map such paths via the Host for proper g3 support. let relative = path.posix.relative(path.dirname(context.fileName), this.node.getSourceFile().fileName) - .replace(TS_DTS_EXTENSION, ''); + .replace(TS_DTS_JS_EXTENSION, ''); // path.relative() does not include the leading './'. if (!relative.startsWith('.')) {