@@ -8091,26 +8091,38 @@ namespace ts {
80918091 return type;
80928092 }
80938093
8094- function getConditionalType(checkType: Type, extendsType: Type, trueType : Type, falseType : Type, aliasSymbol?: Symbol, aliasTypeArguments ?: Type[]): Type {
8094+ function getConditionalType(checkType: Type, extendsType: Type, baseTrueType : Type, baseFalseType : Type, target: ConditionalType, mapper: TypeMapper, aliasSymbol?: Symbol, baseAliasTypeArguments ?: Type[]): Type {
80958095 // Distribute union types over conditional types
80968096 if (checkType.flags & TypeFlags.Union) {
8097- return getUnionType(map((<UnionType>checkType).types, t => getConditionalType(t, extendsType, trueType, falseType )));
8097+ return getUnionType(map((<UnionType>checkType).types, t => getConditionalType(t, extendsType, baseTrueType, baseFalseType, target, mapper )));
80988098 }
80998099 // Return union of trueType and falseType for any and never since they match anything
81008100 if (checkType.flags & (TypeFlags.Any | TypeFlags.Never)) {
8101- return getUnionType([trueType, falseType ]);
8101+ return getUnionType([instantiateType(baseTrueType, mapper), instantiateType(baseFalseType, mapper) ]);
81028102 }
81038103 // Return trueType for a definitely true extends check
81048104 if (isTypeAssignableTo(checkType, extendsType)) {
8105- return trueType ;
8105+ return instantiateType(baseTrueType, mapper) ;
81068106 }
81078107 // Return falseType for a definitely false extends check
81088108 if (!typeMaybeAssignableTo(instantiateType(checkType, anyMapper), instantiateType(extendsType, constraintMapper))) {
8109- return falseType ;
8109+ return instantiateType(baseFalseType, mapper) ;
81108110 }
81118111 // Return a deferred type for a check that is neither definitely true nor definitely false
8112- return createConditionalType(getActualTypeParameter(checkType), extendsType, trueType, falseType,
8113- /*target*/ undefined, /*mapper*/ undefined, aliasSymbol, aliasTypeArguments);
8112+ const erasedCheckType = getActualTypeParameter(checkType);
8113+ const trueType = instantiateType(baseTrueType, mapper);
8114+ const falseType = instantiateType(baseFalseType, mapper);
8115+ const id = target && (target.id + "," + erasedCheckType.id + "," + extendsType.id + "," + trueType.id + "," + falseType.id);
8116+ const cached = id && conditionalTypes.get(id);
8117+ if (cached) {
8118+ return cached;
8119+ }
8120+ const result = createConditionalType(erasedCheckType, extendsType, trueType, falseType,
8121+ target, mapper, aliasSymbol, instantiateTypes(baseAliasTypeArguments, mapper));
8122+ if (id) {
8123+ conditionalTypes.set(id, result);
8124+ }
8125+ return result;
81148126 }
81158127
81168128 function getTypeFromConditionalTypeNode(node: ConditionalTypeNode): Type {
@@ -8119,6 +8131,7 @@ namespace ts {
81198131 links.resolvedType = getConditionalType(
81208132 getTypeFromTypeNode(node.checkType), getTypeFromTypeNode(node.extendsType),
81218133 getTypeFromTypeNode(node.trueType), getTypeFromTypeNode(node.falseType),
8134+ /*target*/ undefined, /*mapper*/ undefined,
81228135 getAliasSymbolForTypeNode(node), getAliasTypeArgumentsForTypeNode(node));
81238136 }
81248137 return links.resolvedType;
@@ -8705,36 +8718,12 @@ namespace ts {
87058718 }
87068719
87078720 function instantiateConditionalType(type: ConditionalType, mapper: TypeMapper): Type {
8708- const checkType = instantiateType(type.checkType, mapper);
8709- // Return union of trueType and falseType for any and never since they match anything
8710- if (checkType.flags & (TypeFlags.Any | TypeFlags.Never)) {
8711- return getUnionType([instantiateType(type.trueType, mapper), instantiateType(type.falseType, mapper)]);
8712- }
8713- const extendsType = instantiateType(type.extendsType, mapper);
8714- // Return trueType for a definitely true extends check
8715- if (isTypeAssignableTo(checkType, extendsType)) {
8716- return instantiateType(type.trueType, mapper);
8717- }
8718- // Return falseType for a definitely false extends check
8719- if (!typeMaybeAssignableTo(instantiateType(checkType, anyMapper), instantiateType(extendsType, constraintMapper))) {
8720- return instantiateType(type.falseType, mapper);
8721- }
8722- // Return a deferred type for a check that is neither definitely true nor definitely false
8723- const erasedCheckType = getActualTypeParameter(checkType);
8724- const trueType = instantiateType(type.trueType, mapper);
8725- const falseType = instantiateType(type.falseType, mapper);
8726- const id = type.id + "," + erasedCheckType.id + "," + extendsType.id + "," + trueType.id + "," + falseType.id;
8727- let result = conditionalTypes.get(id);
8728- if (!result) {
8729- result = createConditionalType(erasedCheckType, extendsType, trueType, falseType,
8730- type, mapper, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
8731- conditionalTypes.set(id, result);
8732- }
8733- return result;
8721+ return getConditionalType(instantiateType(type.checkType, mapper), instantiateType(type.extendsType, mapper),
8722+ type.trueType, type.falseType, type, mapper, type.aliasSymbol, type.aliasTypeArguments);
87348723 }
87358724
87368725 function instantiateType(type: Type, mapper: TypeMapper): Type {
8737- if (type && mapper !== identityMapper) {
8726+ if (type && mapper && mapper !== identityMapper) {
87388727 if (type.flags & TypeFlags.TypeParameter) {
87398728 return mapper(<TypeParameter>type);
87408729 }
0 commit comments