From 5204fd5c5f7b881ee12d4632d893ede2e96c40a3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 19 Jan 2018 17:06:09 -0800 Subject: [PATCH] Add T is related to { [P in xxx]: T[P] } type relationship --- src/compiler/checker.ts | 22 +++++++++++++++------- src/compiler/types.ts | 2 ++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2cd8e5e1e3d..d0fe701760d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6968,7 +6968,7 @@ namespace ts { // type references and type alias instantiations because subsitution types are no longer necessary once // the type arguments have been validated against their corresponding type parameter constraints. function eraseSubstitutionType(type: Type) { - return type.flags & TypeFlags.Substitution ? (type).typeParameter : type + return type.flags & TypeFlags.Substitution ? (type).typeParameter : type; } function createTypeReference(target: GenericType, typeArguments: Type[]): TypeReference { @@ -9821,13 +9821,21 @@ namespace ts { } } } - else if (isGenericMappedType(target) && !isGenericMappedType(source) && getConstraintTypeFromMappedType(target) === getIndexType(source)) { + else if (isGenericMappedType(target)) { + // A source type T is related to a target type { [P in X]: T[P] } + const template = getTemplateTypeFromMappedType(target); + if (template.flags & TypeFlags.IndexedAccess && (template).objectType === source && + (template).indexType === getTypeParameterFromMappedType(target)) { + return Ternary.True; + } // A source type T is related to a target type { [P in keyof T]: X } if T[P] is related to X. - const indexedAccessType = getIndexedAccessType(source, getTypeParameterFromMappedType(target)); - const templateType = getTemplateTypeFromMappedType(target); - if (result = isRelatedTo(indexedAccessType, templateType, reportErrors)) { - errorInfo = saveErrorInfo; - return result; + if (!isGenericMappedType(source) && getConstraintTypeFromMappedType(target) === getIndexType(source)) { + const indexedAccessType = getIndexedAccessType(source, getTypeParameterFromMappedType(target)); + const templateType = getTemplateTypeFromMappedType(target); + if (result = isRelatedTo(indexedAccessType, templateType, reportErrors)) { + errorInfo = saveErrorInfo; + return result; + } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3b00e81456f..b9f36387243 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3794,7 +3794,9 @@ namespace ts { extendsType: Type; trueType: Type; falseType: Type; + /* @internal */ target?: ConditionalType; + /* @internal */ mapper?: TypeMapper; }