@@ -394,7 +394,6 @@ namespace ts {
394
394
const intersectionTypes = createMap<IntersectionType>();
395
395
const literalTypes = createMap<LiteralType>();
396
396
const indexedAccessTypes = createMap<IndexedAccessType>();
397
- const conditionalTypes = createMap<Type>();
398
397
const substitutionTypes = createMap<SubstitutionType>();
399
398
const evolvingArrayTypes: EvolvingArrayType[] = [];
400
399
const undefinedProperties = createMap<Symbol>() as UnderscoreEscapedMap<Symbol>;
@@ -3648,8 +3647,8 @@ namespace ts {
3648
3647
context.inferTypeParameters = (<ConditionalType>type).root.inferTypeParameters;
3649
3648
const extendsTypeNode = typeToTypeNodeHelper((<ConditionalType>type).extendsType, context);
3650
3649
context.inferTypeParameters = saveInferTypeParameters;
3651
- const trueTypeNode = typeToTypeNodeHelper((<ConditionalType>type).trueType , context);
3652
- const falseTypeNode = typeToTypeNodeHelper((<ConditionalType>type).falseType , context);
3650
+ const trueTypeNode = typeToTypeNodeHelper(getTrueTypeFromConditionalType (<ConditionalType>type), context);
3651
+ const falseTypeNode = typeToTypeNodeHelper(getFalseTypeFromConditionalType (<ConditionalType>type), context);
3653
3652
context.approximateLength += 15;
3654
3653
return createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode);
3655
3654
}
@@ -7674,7 +7673,7 @@ namespace ts {
7674
7673
// just `any`. This result is _usually_ unwanted - so instead here we elide an `any` branch from the constraint type,
7675
7674
// in effect treating `any` like `never` rather than `unknown` in this location.
7676
7675
const trueConstraint = getInferredTrueTypeFromConditionalType(type);
7677
- const falseConstraint = type.falseType ;
7676
+ const falseConstraint = getFalseTypeFromConditionalType( type) ;
7678
7677
type.resolvedDefaultConstraint = isTypeAny(trueConstraint) ? falseConstraint : isTypeAny(falseConstraint) ? trueConstraint : getUnionType([trueConstraint, falseConstraint]);
7679
7678
}
7680
7679
return type.resolvedDefaultConstraint;
@@ -10377,37 +10376,23 @@ namespace ts {
10377
10376
if (checkType === wildcardType || extendsType === wildcardType) {
10378
10377
return wildcardType;
10379
10378
}
10380
- const trueType = instantiateType(root.trueType, mapper);
10381
- const falseType = instantiateType(root.falseType, mapper);
10382
- const instantiationId = `${root.isDistributive ? "d" : ""}${getTypeId(checkType)}>${getTypeId(extendsType)}?${getTypeId(trueType)}:${getTypeId(falseType)}`;
10383
- const result = conditionalTypes.get(instantiationId);
10384
- if (result) {
10385
- return result;
10386
- }
10387
- const newResult = getConditionalTypeWorker(root, mapper, checkType, extendsType, trueType, falseType);
10388
- conditionalTypes.set(instantiationId, newResult);
10389
- return newResult;
10390
- }
10391
-
10392
- function getConditionalTypeWorker(root: ConditionalRoot, mapper: TypeMapper | undefined, checkType: Type, extendsType: Type, trueType: Type, falseType: Type) {
10393
10379
// Simplifications for types of the form `T extends U ? T : never` and `T extends U ? never : T`.
10394
- if (falseType.flags & TypeFlags.Never && getActualTypeVariable(trueType) === getActualTypeVariable(checkType)) {
10380
+ if (root. falseType.flags & TypeFlags.Never && getActualTypeVariable(root. trueType) === getActualTypeVariable(root. checkType)) {
10395
10381
if (checkType.flags & TypeFlags.Any || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true
10396
- return trueType;
10382
+ return instantiateType(root. trueType, mapper) ;
10397
10383
}
10398
10384
else if (isIntersectionEmpty(checkType, extendsType)) { // Always false
10399
10385
return neverType;
10400
10386
}
10401
10387
}
10402
- else if (trueType.flags & TypeFlags.Never && getActualTypeVariable(falseType) === getActualTypeVariable(checkType)) {
10388
+ else if (root. trueType.flags & TypeFlags.Never && getActualTypeVariable(root. falseType) === getActualTypeVariable(root. checkType)) {
10403
10389
if (!(checkType.flags & TypeFlags.Any) && isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true
10404
10390
return neverType;
10405
10391
}
10406
10392
else if (checkType.flags & TypeFlags.Any || isIntersectionEmpty(checkType, extendsType)) { // Always false
10407
- return falseType;
10393
+ return instantiateType(root. falseType, mapper) ;
10408
10394
}
10409
10395
}
10410
-
10411
10396
const checkTypeInstantiable = maybeTypeOfKind(checkType, TypeFlags.Instantiable | TypeFlags.GenericMappedType);
10412
10397
let combinedMapper: TypeMapper | undefined;
10413
10398
if (root.inferTypeParameters) {
@@ -10425,49 +10410,55 @@ namespace ts {
10425
10410
// We attempt to resolve the conditional type only when the check and extends types are non-generic
10426
10411
if (!checkTypeInstantiable && !maybeTypeOfKind(inferredExtendsType, TypeFlags.Instantiable | TypeFlags.GenericMappedType)) {
10427
10412
if (inferredExtendsType.flags & TypeFlags.AnyOrUnknown) {
10428
- return combinedMapper ? instantiateType(root.trueType, combinedMapper) : trueType ;
10413
+ return instantiateType(root.trueType, combinedMapper || mapper) ;
10429
10414
}
10430
10415
// Return union of trueType and falseType for 'any' since it matches anything
10431
10416
if (checkType.flags & TypeFlags.Any) {
10432
- return getUnionType([combinedMapper ? instantiateType(root.trueType, combinedMapper) : trueType, falseType]);
10417
+ return getUnionType([instantiateType(root.trueType, combinedMapper || mapper), instantiateType(root. falseType, mapper) ]);
10433
10418
}
10434
10419
// Return falseType for a definitely false extends check. We check an instantiations of the two
10435
10420
// types with type parameters mapped to the wildcard type, the most permissive instantiations
10436
10421
// possible (the wildcard type is assignable to and from all types). If those are not related,
10437
10422
// then no instantiations will be and we can just return the false branch type.
10438
10423
if (!isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType))) {
10439
- return falseType;
10424
+ return instantiateType(root. falseType, mapper) ;
10440
10425
}
10441
10426
// Return trueType for a definitely true extends check. We check instantiations of the two
10442
10427
// types with type parameters mapped to their restrictive form, i.e. a form of the type parameter
10443
10428
// that has no constraint. This ensures that, for example, the type
10444
10429
// type Foo<T extends { x: any }> = T extends { x: string } ? string : number
10445
10430
// doesn't immediately resolve to 'string' instead of being deferred.
10446
10431
if (isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(inferredExtendsType))) {
10447
- return combinedMapper ? instantiateType(root.trueType, combinedMapper) : trueType ;
10432
+ return instantiateType(root.trueType, combinedMapper || mapper) ;
10448
10433
}
10449
10434
}
10450
10435
// Return a deferred type for a check that is neither definitely true nor definitely false
10451
- return getDeferredConditionalType(root, mapper, combinedMapper, checkType, extendsType, trueType, falseType );
10436
+ return getDeferredConditionalType(root, mapper, combinedMapper, checkType, extendsType);
10452
10437
}
10453
10438
10454
- function getDeferredConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined, combinedMapper: TypeMapper | undefined, checkType: Type, extendsType: Type, trueType: Type, falseType: Type ) {
10439
+ function getDeferredConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined, combinedMapper: TypeMapper | undefined, checkType: Type, extendsType: Type) {
10455
10440
const erasedCheckType = getActualTypeVariable(checkType);
10456
10441
const result = <ConditionalType>createType(TypeFlags.Conditional);
10457
10442
result.root = root;
10458
10443
result.checkType = erasedCheckType;
10459
10444
result.extendsType = extendsType;
10460
10445
result.mapper = mapper;
10461
10446
result.combinedMapper = combinedMapper;
10462
- result.trueType = trueType;
10463
- result.falseType = falseType;
10464
10447
result.aliasSymbol = root.aliasSymbol;
10465
10448
result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper!); // TODO: GH#18217
10466
10449
return result;
10467
10450
}
10468
10451
10452
+ function getTrueTypeFromConditionalType(type: ConditionalType) {
10453
+ return type.resolvedTrueType || (type.resolvedTrueType = instantiateType(type.root.trueType, type.mapper));
10454
+ }
10455
+
10456
+ function getFalseTypeFromConditionalType(type: ConditionalType) {
10457
+ return type.resolvedFalseType || (type.resolvedFalseType = instantiateType(type.root.falseType, type.mapper));
10458
+ }
10459
+
10469
10460
function getInferredTrueTypeFromConditionalType(type: ConditionalType) {
10470
- return type.resolvedInferredTrueType || (type.resolvedInferredTrueType = instantiateType(type.root.trueType, type.combinedMapper || type.mapper ));
10461
+ return type.resolvedInferredTrueType || (type.resolvedInferredTrueType = type.combinedMapper ? instantiateType(type.root.trueType, type.combinedMapper) : getTrueTypeFromConditionalType( type));
10471
10462
}
10472
10463
10473
10464
function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] | undefined {
@@ -12987,8 +12978,8 @@ namespace ts {
12987
12978
if ((<ConditionalType>source).root.isDistributive === (<ConditionalType>target).root.isDistributive) {
12988
12979
if (result = isRelatedTo((<ConditionalType>source).checkType, (<ConditionalType>target).checkType, /*reportErrors*/ false)) {
12989
12980
if (result &= isRelatedTo((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType, /*reportErrors*/ false)) {
12990
- if (result &= isRelatedTo((<ConditionalType>source).trueType, (<ConditionalType>target).trueType , /*reportErrors*/ false)) {
12991
- if (result &= isRelatedTo((<ConditionalType>source).falseType, (<ConditionalType>target).falseType , /*reportErrors*/ false)) {
12981
+ if (result &= isRelatedTo(getTrueTypeFromConditionalType (<ConditionalType>source), getTrueTypeFromConditionalType (<ConditionalType>target), /*reportErrors*/ false)) {
12982
+ if (result &= isRelatedTo(getFalseTypeFromConditionalType (<ConditionalType>source), getFalseTypeFromConditionalType (<ConditionalType>target), /*reportErrors*/ false)) {
12992
12983
return result;
12993
12984
}
12994
12985
}
@@ -13147,8 +13138,8 @@ namespace ts {
13147
13138
// and Y1 is related to Y2.
13148
13139
if (isTypeIdenticalTo((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType) &&
13149
13140
(isRelatedTo((<ConditionalType>source).checkType, (<ConditionalType>target).checkType) || isRelatedTo((<ConditionalType>target).checkType, (<ConditionalType>source).checkType))) {
13150
- if (result = isRelatedTo((<ConditionalType>source).trueType, (<ConditionalType>target).trueType , reportErrors)) {
13151
- result &= isRelatedTo((<ConditionalType>source).falseType, (<ConditionalType>target).falseType , reportErrors);
13141
+ if (result = isRelatedTo(getTrueTypeFromConditionalType (<ConditionalType>source), getTrueTypeFromConditionalType (<ConditionalType>target), reportErrors)) {
13142
+ result &= isRelatedTo(getFalseTypeFromConditionalType (<ConditionalType>source), getFalseTypeFromConditionalType (<ConditionalType>target), reportErrors);
13152
13143
}
13153
13144
if (result) {
13154
13145
errorInfo = saveErrorInfo;
@@ -15181,12 +15172,12 @@ namespace ts {
15181
15172
else if (source.flags & TypeFlags.Conditional && target.flags & TypeFlags.Conditional) {
15182
15173
inferFromTypes((<ConditionalType>source).checkType, (<ConditionalType>target).checkType);
15183
15174
inferFromTypes((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType);
15184
- inferFromTypes((<ConditionalType>source).trueType, (<ConditionalType>target).trueType );
15185
- inferFromTypes((<ConditionalType>source).falseType, (<ConditionalType>target).falseType );
15175
+ inferFromTypes(getTrueTypeFromConditionalType (<ConditionalType>source), getTrueTypeFromConditionalType (<ConditionalType>target));
15176
+ inferFromTypes(getFalseTypeFromConditionalType (<ConditionalType>source), getFalseTypeFromConditionalType (<ConditionalType>target));
15186
15177
}
15187
15178
else if (target.flags & TypeFlags.Conditional && !contravariant) {
15188
- inferFromTypes(source, (<ConditionalType>target).trueType );
15189
- inferFromTypes(source, (<ConditionalType>target).falseType );
15179
+ inferFromTypes(source, getTrueTypeFromConditionalType (<ConditionalType>target));
15180
+ inferFromTypes(source, getFalseTypeFromConditionalType (<ConditionalType>target));
15190
15181
}
15191
15182
else if (target.flags & TypeFlags.UnionOrIntersection) {
15192
15183
// We infer from types that are not naked type variables first so that inferences we
0 commit comments