fix(ivy): emit generic types when needed in defs in .d.ts file (#25406)

Ivy definitions in .d.ts files often reference the type of a class.
Sometimes, those classes have generic type parameters. When this is
the case, ngtsc needs to emit generic type parameters in the .d.ts
files (usually by passing 'any').

PR Close #25406
This commit is contained in:
Alex Rickabaugh 2018-08-09 14:23:15 +01:00 committed by Matias Niemelä
parent b97d770e60
commit d33e0091df
4 changed files with 18 additions and 3 deletions

View File

@ -156,7 +156,7 @@ export function extractDirectiveMetadata(
inputs: {...inputsFromMeta, ...inputsFromFields}, inputs: {...inputsFromMeta, ...inputsFromFields},
outputs: {...outputsFromMeta, ...outputsFromFields}, queries, selector, outputs: {...outputsFromMeta, ...outputsFromFields}, queries, selector,
type: new WrappedNodeExpr(clazz.name !), type: new WrappedNodeExpr(clazz.name !),
typeArgumentCount: (clazz.typeParameters || []).length, typeArgumentCount: reflector.getGenericArityOfClass(clazz) || 0,
typeSourceSpan: null !, usesInheritance, exportAs, typeSourceSpan: null !, usesInheritance, exportAs,
}; };
return {decoratedElements, decorator: directive, metadata}; return {decoratedElements, decorator: directive, metadata};

View File

@ -411,4 +411,12 @@ export interface ReflectionHost {
isClass(node: ts.Node): boolean; isClass(node: ts.Node): boolean;
hasBaseClass(node: ts.Declaration): 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;
} }

View File

@ -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. * Resolve a `ts.Symbol` to its declaration, keeping track of the `viaModule` along the way.
* *

View File

@ -17,7 +17,7 @@ import * as ts from 'typescript';
import {ClassMemberKind, ReflectionHost} from '../../host'; 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. * Represents a value which cannot be determined statically.
@ -147,7 +147,7 @@ export class ResolvedReference<T extends ts.Node = ts.Node> extends Reference<T>
// TODO(alxhub): investigate the need to map such paths via the Host for proper g3 support. // TODO(alxhub): investigate the need to map such paths via the Host for proper g3 support.
let relative = let relative =
path.posix.relative(path.dirname(context.fileName), this.node.getSourceFile().fileName) 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 './'. // path.relative() does not include the leading './'.
if (!relative.startsWith('.')) { if (!relative.startsWith('.')) {