@@ -9588,8 +9588,7 @@ namespace ts {
95889588 const checkType = (<ConditionalType>type).checkType;
95899589 const constraint = getLowerBoundOfKeyType(checkType);
95909590 if (constraint !== checkType) {
9591- const mapper = makeUnaryTypeMapper((<ConditionalType>type).root.checkType, constraint);
9592- return getConditionalTypeInstantiation(<ConditionalType>type, combineTypeMappers(mapper, (<ConditionalType>type).mapper));
9591+ return getConditionalTypeInstantiation(<ConditionalType>type, prependTypeMapping((<ConditionalType>type).root.checkType, constraint, (<ConditionalType>type).mapper));
95939592 }
95949593 }
95959594 return type;
@@ -9639,7 +9638,7 @@ namespace ts {
96399638 // Create a mapper from T to the current iteration type constituent. Then, if the
96409639 // mapped type is itself an instantiated type, combine the iteration mapper with the
96419640 // instantiation mapper.
9642- const templateMapper = addTypeMapping (type.mapper, typeParameter, t);
9641+ const templateMapper = appendTypeMapping (type.mapper, typeParameter, t);
96439642 // If the current iteration type constituent is a string literal type, create a property.
96449643 // Otherwise, for type string create a string index signature.
96459644 if (isTypeUsableAsPropertyName(t)) {
@@ -9943,8 +9942,7 @@ namespace ts {
99439942 const simplified = getSimplifiedType(type.checkType, /*writing*/ false);
99449943 const constraint = simplified === type.checkType ? getConstraintOfType(simplified) : simplified;
99459944 if (constraint && constraint !== type.checkType) {
9946- const mapper = makeUnaryTypeMapper(type.root.checkType, constraint);
9947- const instantiated = getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper));
9945+ const instantiated = getConditionalTypeInstantiation(type, prependTypeMapping(type.root.checkType, constraint, type.mapper));
99489946 if (!(instantiated.flags & TypeFlags.Never)) {
99499947 return instantiated;
99509948 }
@@ -10175,8 +10173,7 @@ namespace ts {
1017510173 if (typeVariable) {
1017610174 const constraint = getConstraintOfTypeParameter(typeVariable);
1017710175 if (constraint && (isArrayType(constraint) || isTupleType(constraint))) {
10178- const mapper = makeUnaryTypeMapper(typeVariable, constraint);
10179- return instantiateType(type, combineTypeMappers(mapper, type.mapper));
10176+ return instantiateType(type, prependTypeMapping(typeVariable, constraint, type.mapper));
1018010177 }
1018110178 }
1018210179 return type;
@@ -12903,7 +12900,7 @@ namespace ts {
1290312900 // types rules (i.e. proper contravariance) for inferences.
1290412901 inferTypes(context.inferences, checkType, extendsType, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict);
1290512902 }
12906- combinedMapper = combineTypeMappers (mapper, context.mapper);
12903+ combinedMapper = mergeTypeMappers (mapper, context.mapper);
1290712904 }
1290812905 // Instantiate the extends type including inferences for 'infer T' type parameters
1290912906 const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType;
@@ -13543,37 +13540,39 @@ namespace ts {
1354313540 }
1354413541
1354513542 function createTypeMapper(sources: readonly TypeParameter[], targets: readonly Type[] | undefined): TypeMapper {
13546- return sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) :
13547- sources.length === 2 ? makeSimpleTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) :
13548- makeArrayTypeMapper(sources, targets);
13543+ return sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) : makeArrayTypeMapper(sources, targets);
1354913544 }
1355013545
13551- function getMappedType(type: Type, map : TypeMapper): Type {
13552- switch (map .kind) {
13546+ function getMappedType(type: Type, mapper : TypeMapper): Type {
13547+ switch (mapper .kind) {
1355313548 case TypeMapKind.Simple:
13554- return type === map.source1 ? map.target1 : type === map.source2 ? map.target2 : type;
13549+ return type === mapper.source ? mapper.target : type;
1355513550 case TypeMapKind.Array:
13556- const sources = map .sources;
13557- const targets = map .targets;
13551+ const sources = mapper .sources;
13552+ const targets = mapper .targets;
1355813553 for (let i = 0; i < sources.length; i++) {
1355913554 if (type === sources[i]) {
1356013555 return targets ? targets[i] : anyType;
1356113556 }
1356213557 }
1356313558 return type;
1356413559 case TypeMapKind.Function:
13565- return map .func(type);
13560+ return mapper .func(type);
1356613561 case TypeMapKind.Composite:
13567- return instantiateType(getMappedType(type, map.mapper1), map.mapper2);
13562+ case TypeMapKind.Merged:
13563+ if (type === mapper.cachedSource) return mapper.cachedTarget;
13564+ const t1 = getMappedType(type, mapper.mapper1);
13565+ const t2 = t1 !== type && mapper.kind === TypeMapKind.Composite ? instantiateType(t1, mapper.mapper2) : getMappedType(t1, mapper.mapper2);
13566+ if (t2 !== type) {
13567+ mapper.cachedSource = type;
13568+ mapper.cachedTarget = t2;
13569+ }
13570+ return t2;
1356813571 }
1356913572 }
1357013573
1357113574 function makeUnaryTypeMapper(source: Type, target: Type): TypeMapper {
13572- return makeSimpleTypeMapper(source, target, anyType, anyType);
13573- }
13574-
13575- function makeSimpleTypeMapper(source1: Type, target1: Type, source2: Type, target2: Type): TypeMapper {
13576- return { kind: TypeMapKind.Simple, source1, target1, source2, target2 };
13575+ return { kind: TypeMapKind.Simple, source, target };
1357713576 }
1357813577
1357913578 function makeArrayTypeMapper(sources: readonly TypeParameter[], targets: readonly Type[] | undefined): TypeMapper {
@@ -13584,8 +13583,8 @@ namespace ts {
1358413583 return { kind: TypeMapKind.Function, func };
1358513584 }
1358613585
13587- function makeCompositeTypeMapper(mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
13588- return { kind: TypeMapKind.Composite , mapper1, mapper2 };
13586+ function makeCompositeTypeMapper(kind: TypeMapKind.Composite | TypeMapKind.Merged, mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
13587+ return { kind, mapper1, mapper2, cachedSource: undefined!, cachedTarget: undefined! };
1358913588 }
1359013589
1359113590 function createTypeEraser(sources: readonly TypeParameter[]): TypeMapper {
@@ -13600,27 +13599,20 @@ namespace ts {
1360013599 return makeFunctionTypeMapper(t => findIndex(context.inferences, info => info.typeParameter === t) >= index ? unknownType : t);
1360113600 }
1360213601
13603- function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper;
13604- function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper | undefined): TypeMapper;
13605- function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
13606- return !mapper1 ? mapper2 : !mapper2 ? mapper1 : makeCompositeTypeMapper(mapper1, mapper2);
13602+ function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper {
13603+ return mapper1 ? makeCompositeTypeMapper(TypeMapKind.Composite, mapper1, mapper2) : mapper2;
1360713604 }
1360813605
13609- function addTypeMapping(mapper: TypeMapper | undefined, source: TypeParameter, target: Type) {
13610- return mapper && mapper.kind === TypeMapKind.Simple && mapper.source2 === mapper.target2 ?
13611- makeSimpleTypeMapper(mapper.source1, mapper.target1, source, target) :
13612- combineTypeMappers(mapper, makeUnaryTypeMapper(source, target));
13606+ function mergeTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper {
13607+ return mapper1 ? makeCompositeTypeMapper(TypeMapKind.Merged, mapper1, mapper2) : mapper2;
1361313608 }
1361413609
13615- function createReplacementMapper(source: Type, target: Type, baseMapper: TypeMapper): TypeMapper {
13616- switch (baseMapper.kind) {
13617- case TypeMapKind.Simple:
13618- return makeSimpleTypeMapper(baseMapper.source1, baseMapper.source1 === source ? target : baseMapper.target1,
13619- baseMapper.source2, baseMapper.source2 === source ? target : baseMapper.target2);
13620- case TypeMapKind.Array:
13621- return makeArrayTypeMapper(baseMapper.sources, map(baseMapper.targets, (t, i) => baseMapper.sources[i] === source ? target : t));
13622- }
13623- return makeFunctionTypeMapper(t => t === source ? target : getMappedType(t, baseMapper));
13610+ function prependTypeMapping(source: Type, target: Type, mapper: TypeMapper | undefined) {
13611+ return !mapper ? makeUnaryTypeMapper(source, target) : makeCompositeTypeMapper(TypeMapKind.Merged, makeUnaryTypeMapper(source, target), mapper);
13612+ }
13613+
13614+ function appendTypeMapping(mapper: TypeMapper | undefined, source: Type, target: Type) {
13615+ return !mapper ? makeUnaryTypeMapper(source, target) : makeCompositeTypeMapper(TypeMapKind.Merged, mapper, makeUnaryTypeMapper(source, target));
1362413616 }
1362513617
1362613618 function getRestrictiveTypeParameter(tp: TypeParameter) {
@@ -13815,7 +13807,7 @@ namespace ts {
1381513807 if (typeVariable !== mappedTypeVariable) {
1381613808 return mapType(getReducedType(mappedTypeVariable), t => {
1381713809 if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && t !== errorType) {
13818- const replacementMapper = createReplacementMapper (typeVariable, t, mapper);
13810+ const replacementMapper = prependTypeMapping (typeVariable, t, mapper);
1381913811 return isArrayType(t) ? instantiateMappedArrayType(t, type, replacementMapper) :
1382013812 isTupleType(t) ? instantiateMappedTupleType(t, type, replacementMapper) :
1382113813 instantiateAnonymousType(type, replacementMapper);
@@ -13851,7 +13843,7 @@ namespace ts {
1385113843 }
1385213844
1385313845 function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) {
13854- const templateMapper = addTypeMapping (mapper, getTypeParameterFromMappedType(type), key);
13846+ const templateMapper = appendTypeMapping (mapper, getTypeParameterFromMappedType(type), key);
1385513847 const propType = instantiateType(getTemplateTypeFromMappedType(<MappedType>type.target || type), templateMapper);
1385613848 const modifiers = getMappedTypeModifiers(type);
1385713849 return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType) :
@@ -13904,7 +13896,7 @@ namespace ts {
1390413896 const checkType = <TypeParameter>root.checkType;
1390513897 const instantiatedType = getMappedType(checkType, mapper);
1390613898 if (checkType !== instantiatedType && instantiatedType.flags & (TypeFlags.Union | TypeFlags.Never)) {
13907- return mapType(instantiatedType, t => getConditionalType(root, createReplacementMapper (checkType, t, mapper)));
13899+ return mapType(instantiatedType, t => getConditionalType(root, prependTypeMapping (checkType, t, mapper)));
1390813900 }
1390913901 }
1391013902 return getConditionalType(root, mapper);
@@ -18743,7 +18735,7 @@ namespace ts {
1874318735 if (defaultType) {
1874418736 // Instantiate the default type. Any forward reference to a type
1874518737 // parameter should be instantiated to the empty object type.
18746- inferredType = instantiateType(defaultType, combineTypeMappers (createBackreferenceMapper(context, index), context.nonFixingMapper));
18738+ inferredType = instantiateType(defaultType, mergeTypeMappers (createBackreferenceMapper(context, index), context.nonFixingMapper));
1874718739 }
1874818740 }
1874918741 }
0 commit comments