@@ -9588,8 +9588,7 @@ namespace ts {
9588
9588
const checkType = (<ConditionalType>type).checkType;
9589
9589
const constraint = getLowerBoundOfKeyType(checkType);
9590
9590
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));
9593
9592
}
9594
9593
}
9595
9594
return type;
@@ -9639,7 +9638,7 @@ namespace ts {
9639
9638
// Create a mapper from T to the current iteration type constituent. Then, if the
9640
9639
// mapped type is itself an instantiated type, combine the iteration mapper with the
9641
9640
// instantiation mapper.
9642
- const templateMapper = addTypeMapping (type.mapper, typeParameter, t);
9641
+ const templateMapper = appendTypeMapping (type.mapper, typeParameter, t);
9643
9642
// If the current iteration type constituent is a string literal type, create a property.
9644
9643
// Otherwise, for type string create a string index signature.
9645
9644
if (isTypeUsableAsPropertyName(t)) {
@@ -9943,8 +9942,7 @@ namespace ts {
9943
9942
const simplified = getSimplifiedType(type.checkType, /*writing*/ false);
9944
9943
const constraint = simplified === type.checkType ? getConstraintOfType(simplified) : simplified;
9945
9944
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));
9948
9946
if (!(instantiated.flags & TypeFlags.Never)) {
9949
9947
return instantiated;
9950
9948
}
@@ -10175,8 +10173,7 @@ namespace ts {
10175
10173
if (typeVariable) {
10176
10174
const constraint = getConstraintOfTypeParameter(typeVariable);
10177
10175
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));
10180
10177
}
10181
10178
}
10182
10179
return type;
@@ -12903,7 +12900,7 @@ namespace ts {
12903
12900
// types rules (i.e. proper contravariance) for inferences.
12904
12901
inferTypes(context.inferences, checkType, extendsType, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict);
12905
12902
}
12906
- combinedMapper = combineTypeMappers (mapper, context.mapper);
12903
+ combinedMapper = mergeTypeMappers (mapper, context.mapper);
12907
12904
}
12908
12905
// Instantiate the extends type including inferences for 'infer T' type parameters
12909
12906
const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType;
@@ -13543,37 +13540,39 @@ namespace ts {
13543
13540
}
13544
13541
13545
13542
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);
13549
13544
}
13550
13545
13551
- function getMappedType(type: Type, map : TypeMapper): Type {
13552
- switch (map .kind) {
13546
+ function getMappedType(type: Type, mapper : TypeMapper): Type {
13547
+ switch (mapper .kind) {
13553
13548
case TypeMapKind.Simple:
13554
- return type === map.source1 ? map.target1 : type === map.source2 ? map.target2 : type;
13549
+ return type === mapper.source ? mapper.target : type;
13555
13550
case TypeMapKind.Array:
13556
- const sources = map .sources;
13557
- const targets = map .targets;
13551
+ const sources = mapper .sources;
13552
+ const targets = mapper .targets;
13558
13553
for (let i = 0; i < sources.length; i++) {
13559
13554
if (type === sources[i]) {
13560
13555
return targets ? targets[i] : anyType;
13561
13556
}
13562
13557
}
13563
13558
return type;
13564
13559
case TypeMapKind.Function:
13565
- return map .func(type);
13560
+ return mapper .func(type);
13566
13561
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;
13568
13571
}
13569
13572
}
13570
13573
13571
13574
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 };
13577
13576
}
13578
13577
13579
13578
function makeArrayTypeMapper(sources: readonly TypeParameter[], targets: readonly Type[] | undefined): TypeMapper {
@@ -13584,8 +13583,8 @@ namespace ts {
13584
13583
return { kind: TypeMapKind.Function, func };
13585
13584
}
13586
13585
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! };
13589
13588
}
13590
13589
13591
13590
function createTypeEraser(sources: readonly TypeParameter[]): TypeMapper {
@@ -13600,27 +13599,20 @@ namespace ts {
13600
13599
return makeFunctionTypeMapper(t => findIndex(context.inferences, info => info.typeParameter === t) >= index ? unknownType : t);
13601
13600
}
13602
13601
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;
13607
13604
}
13608
13605
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;
13613
13608
}
13614
13609
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));
13624
13616
}
13625
13617
13626
13618
function getRestrictiveTypeParameter(tp: TypeParameter) {
@@ -13815,7 +13807,7 @@ namespace ts {
13815
13807
if (typeVariable !== mappedTypeVariable) {
13816
13808
return mapType(getReducedType(mappedTypeVariable), t => {
13817
13809
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);
13819
13811
return isArrayType(t) ? instantiateMappedArrayType(t, type, replacementMapper) :
13820
13812
isTupleType(t) ? instantiateMappedTupleType(t, type, replacementMapper) :
13821
13813
instantiateAnonymousType(type, replacementMapper);
@@ -13851,7 +13843,7 @@ namespace ts {
13851
13843
}
13852
13844
13853
13845
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);
13855
13847
const propType = instantiateType(getTemplateTypeFromMappedType(<MappedType>type.target || type), templateMapper);
13856
13848
const modifiers = getMappedTypeModifiers(type);
13857
13849
return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType) :
@@ -13904,7 +13896,7 @@ namespace ts {
13904
13896
const checkType = <TypeParameter>root.checkType;
13905
13897
const instantiatedType = getMappedType(checkType, mapper);
13906
13898
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)));
13908
13900
}
13909
13901
}
13910
13902
return getConditionalType(root, mapper);
@@ -18743,7 +18735,7 @@ namespace ts {
18743
18735
if (defaultType) {
18744
18736
// Instantiate the default type. Any forward reference to a type
18745
18737
// 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));
18747
18739
}
18748
18740
}
18749
18741
}
0 commit comments