fix(ivy): types in .d.ts files should account for generics (#24862)

Ivy definition types have a generic type which specifies the return
type of the factory function. For example:

static ngDirectiveDef<NgForOf, '[ngFor][ngForOf]'>

However, in this case NgForOf itself has a type parameter <T>. Thus,
writing the above is incorrect.

This commit modifies ngtsc to understand the genericness of NgForOf and
to write the following:

static ngDirectiveDef<NgForOf<any>, '[ngFor][ngForOf]'>

PR Close #24862
This commit is contained in:
Alex Rickabaugh
2018-07-13 14:49:01 -07:00
committed by Victor Berchet
parent 2b8b647006
commit 41ef75869c
8 changed files with 53 additions and 12 deletions

View File

@ -36,3 +36,14 @@ export function convertMetaToOutput(meta: any, ctx: OutputContext): o.Expression
throw new Error(`Internal error: Unsupported or unknown metadata: ${meta}`);
}
export function typeWithParameters(type: o.Expression, numParams: number): o.ExpressionType {
let params: o.Type[]|null = null;
if (numParams > 0) {
params = [];
for (let i = 0; i < numParams; i++) {
params.push(o.DYNAMIC_TYPE);
}
}
return o.expressionType(type, null, params);
}

View File

@ -25,6 +25,11 @@ export interface R3DirectiveMetadata {
*/
type: o.Expression;
/**
* Number of generic type parameters of the type itself.
*/
typeArgumentCount: number;
/**
* A source span for the directive type.
*/

View File

@ -20,11 +20,12 @@ import {ParseSourceSpan, typeSourceSpan} from '../../parse_util';
import {CssSelector, SelectorMatcher} from '../../selector';
import {BindingParser} from '../../template_parser/binding_parser';
import {OutputContext, error} from '../../util';
import * as t from '../r3_ast';
import {R3DependencyMetadata, R3ResolvedDependencyType, compileFactoryFunction, dependenciesFromGlobalMetadata} from '../r3_factory';
import {Identifiers as R3} from '../r3_identifiers';
import {Render3ParseResult} from '../r3_template_transform';
import {typeWithParameters} from '../util';
import {R3ComponentDef, R3ComponentMetadata, R3DirectiveDef, R3DirectiveMetadata, R3QueryMetadata} from './api';
import {BindingScope, TemplateDefinitionBuilder} from './template';
import {CONTEXT_NAME, DefinitionMap, ID_SEPARATOR, MEANING_SEPARATOR, TEMPORARY_NAME, asLiteral, conditionallyCreateMapObjectLiteral, getQueryPredicate, temporaryAllocator, unsupported} from './util';
@ -93,9 +94,10 @@ export function compileDirectiveFromMetadata(
// string literal, which must be on one line.
const selectorForType = (meta.selector || '').replace(/\n/g, '');
const type = new o.ExpressionType(o.importExpr(
R3.DirectiveDef,
[new o.ExpressionType(meta.type), new o.ExpressionType(o.literal(selectorForType))]));
const type = new o.ExpressionType(o.importExpr(R3.DirectiveDef, [
typeWithParameters(meta.type, meta.typeArgumentCount),
new o.ExpressionType(o.literal(selectorForType))
]));
return {expression, type};
}
@ -167,9 +169,10 @@ export function compileComponentFromMetadata(
const selectorForType = (meta.selector || '').replace(/\n/g, '');
const expression = o.importExpr(R3.defineComponent).callFn([definitionMap.toLiteralMap()]);
const type = new o.ExpressionType(o.importExpr(
R3.ComponentDef,
[new o.ExpressionType(meta.type), new o.ExpressionType(o.literal(selectorForType))]));
const type = new o.ExpressionType(o.importExpr(R3.ComponentDef, [
typeWithParameters(meta.type, meta.typeArgumentCount),
new o.ExpressionType(o.literal(selectorForType))
]));
return {expression, type};
}
@ -252,6 +255,7 @@ function directiveMetadataFromGlobalMetadata(
return {
name,
type: outputCtx.importExpr(directive.type.reference),
typeArgumentCount: 0,
typeSourceSpan:
typeSourceSpan(directive.isComponent ? 'Component' : 'Directive', directive.type),
selector: directive.selector,