Merge pull request #12515 from Microsoft/fixMappedTypeInference

Include mapped types in type inference infinite recursion check
This commit is contained in:
Anders Hejlsberg
2016-11-26 18:14:18 -08:00
committed by GitHub
5 changed files with 93 additions and 17 deletions

View File

@@ -8590,19 +8590,6 @@ namespace ts {
}
}
else {
if (getObjectFlags(target) & ObjectFlags.Mapped) {
const constraintType = getConstraintTypeFromMappedType(<MappedType>target);
if (getObjectFlags(source) & ObjectFlags.Mapped) {
inferFromTypes(getConstraintTypeFromMappedType(<MappedType>source), constraintType);
inferFromTypes(getTemplateTypeFromMappedType(<MappedType>source), getTemplateTypeFromMappedType(<MappedType>target));
return;
}
if (constraintType.flags & TypeFlags.TypeParameter) {
inferFromTypes(getIndexType(source), constraintType);
inferFromTypes(getUnionType(map(getPropertiesOfType(source), getTypeOfSymbol)), getTemplateTypeFromMappedType(<MappedType>target));
return;
}
}
source = getApparentType(source);
if (source.flags & TypeFlags.Object) {
if (isInProcess(source, target)) {
@@ -8623,15 +8610,32 @@ namespace ts {
sourceStack[depth] = source;
targetStack[depth] = target;
depth++;
inferFromProperties(source, target);
inferFromSignatures(source, target, SignatureKind.Call);
inferFromSignatures(source, target, SignatureKind.Construct);
inferFromIndexTypes(source, target);
inferFromObjectTypes(source, target);
depth--;
}
}
}
function inferFromObjectTypes(source: Type, target: Type) {
if (getObjectFlags(target) & ObjectFlags.Mapped) {
const constraintType = getConstraintTypeFromMappedType(<MappedType>target);
if (getObjectFlags(source) & ObjectFlags.Mapped) {
inferFromTypes(getConstraintTypeFromMappedType(<MappedType>source), constraintType);
inferFromTypes(getTemplateTypeFromMappedType(<MappedType>source), getTemplateTypeFromMappedType(<MappedType>target));
return;
}
if (constraintType.flags & TypeFlags.TypeParameter) {
inferFromTypes(getIndexType(source), constraintType);
inferFromTypes(getUnionType(map(getPropertiesOfType(source), getTypeOfSymbol)), getTemplateTypeFromMappedType(<MappedType>target));
return;
}
}
inferFromProperties(source, target);
inferFromSignatures(source, target, SignatureKind.Call);
inferFromSignatures(source, target, SignatureKind.Construct);
inferFromIndexTypes(source, target);
}
function inferFromProperties(source: Type, target: Type) {
const properties = getPropertiesOfObjectType(target);
for (const targetProp of properties) {

View File

@@ -0,0 +1,12 @@
//// [mappedTypeInferenceCircularity.ts]
// Repro from #12511
type HTML = { [K in 'div']: Block<HTML> };
type Block<P> = <T>(func: HTML) => {};
declare var h: HTML;
h.div(h);
//// [mappedTypeInferenceCircularity.js]
// Repro from #12511
h.div(h);

View File

@@ -0,0 +1,26 @@
=== tests/cases/compiler/mappedTypeInferenceCircularity.ts ===
// Repro from #12511
type HTML = { [K in 'div']: Block<HTML> };
>HTML : Symbol(HTML, Decl(mappedTypeInferenceCircularity.ts, 0, 0))
>K : Symbol(K, Decl(mappedTypeInferenceCircularity.ts, 2, 15))
>Block : Symbol(Block, Decl(mappedTypeInferenceCircularity.ts, 2, 42))
>HTML : Symbol(HTML, Decl(mappedTypeInferenceCircularity.ts, 0, 0))
type Block<P> = <T>(func: HTML) => {};
>Block : Symbol(Block, Decl(mappedTypeInferenceCircularity.ts, 2, 42))
>P : Symbol(P, Decl(mappedTypeInferenceCircularity.ts, 3, 11))
>T : Symbol(T, Decl(mappedTypeInferenceCircularity.ts, 3, 17))
>func : Symbol(func, Decl(mappedTypeInferenceCircularity.ts, 3, 20))
>HTML : Symbol(HTML, Decl(mappedTypeInferenceCircularity.ts, 0, 0))
declare var h: HTML;
>h : Symbol(h, Decl(mappedTypeInferenceCircularity.ts, 5, 11))
>HTML : Symbol(HTML, Decl(mappedTypeInferenceCircularity.ts, 0, 0))
h.div(h);
>h.div : Symbol(div)
>h : Symbol(h, Decl(mappedTypeInferenceCircularity.ts, 5, 11))
>div : Symbol(div)
>h : Symbol(h, Decl(mappedTypeInferenceCircularity.ts, 5, 11))

View File

@@ -0,0 +1,27 @@
=== tests/cases/compiler/mappedTypeInferenceCircularity.ts ===
// Repro from #12511
type HTML = { [K in 'div']: Block<HTML> };
>HTML : HTML
>K : K
>Block : Block<P>
>HTML : HTML
type Block<P> = <T>(func: HTML) => {};
>Block : Block<P>
>P : P
>T : T
>func : HTML
>HTML : HTML
declare var h: HTML;
>h : HTML
>HTML : HTML
h.div(h);
>h.div(h) : {}
>h.div : Block<HTML>
>h : HTML
>div : Block<HTML>
>h : HTML

View File

@@ -0,0 +1,7 @@
// Repro from #12511
type HTML = { [K in 'div']: Block<HTML> };
type Block<P> = <T>(func: HTML) => {};
declare var h: HTML;
h.div(h);