@@ -9853,7 +9853,7 @@ namespace ts {
98539853 }
98549854
98559855 function getPropertiesOfType(type: Type): Symbol[] {
9856- type = getApparentType(getReducedType( type) );
9856+ type = getApparentType(type);
98579857 return type.flags & TypeFlags.UnionOrIntersection ?
98589858 getPropertiesOfUnionOrIntersectionType(<UnionType>type) :
98599859 getPropertiesOfObjectType(type);
@@ -10195,6 +10195,7 @@ namespace ts {
1019510195 * type itself.
1019610196 */
1019710197 function getApparentType(type: Type): Type {
10198+ type = getReducedType(type);
1019810199 const t = type.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(type) || unknownType : type;
1019910200 return getObjectFlags(t) & ObjectFlags.Mapped ? getApparentTypeOfMappedType(<MappedType>t) :
1020010201 t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(<IntersectionType>t) :
@@ -10352,15 +10353,21 @@ namespace ts {
1035210353 * no constituent property has type 'never', but the intersection of the constituent property types is 'never'.
1035310354 */
1035410355 function getReducedType(type: Type): Type {
10355- if (type.flags & TypeFlags.Union && (<UnionType>type).objectFlags & ObjectFlags.ContainsIntersections ) {
10356+ if (type.flags & TypeFlags.Union && (<UnionType>type).objectFlags & ObjectFlags.ContainsReducibles ) {
1035610357 return (<UnionType>type).resolvedReducedType || ((<UnionType>type).resolvedReducedType = getReducedUnionType(<UnionType>type));
1035710358 }
1035810359 else if (type.flags & TypeFlags.Intersection) {
1035910360 if (!((<IntersectionType>type).objectFlags & ObjectFlags.IsNeverIntersectionComputed)) {
1036010361 (<IntersectionType>type).objectFlags |= ObjectFlags.IsNeverIntersectionComputed |
1036110362 (some(getPropertiesOfUnionOrIntersectionType(<IntersectionType>type), isDiscriminantWithNeverType) ? ObjectFlags.IsNeverIntersection : 0);
1036210363 }
10363- return (<IntersectionType>type).objectFlags & ObjectFlags.IsNeverIntersection ? neverType : type;
10364+ if ((<IntersectionType>type).objectFlags & ObjectFlags.IsNeverIntersection) {
10365+ return neverType;
10366+ }
10367+ return (<IntersectionType>type).resolvedReducedType || ((<IntersectionType>type).resolvedReducedType = getReducedIntersectionType(<IntersectionType>type));
10368+ }
10369+ else if (type.flags & TypeFlags.Conditional) {
10370+ return getReducedConditionalType(type as ConditionalType);
1036410371 }
1036510372 return type;
1036610373 }
@@ -10377,6 +10384,18 @@ namespace ts {
1037710384 return reduced;
1037810385 }
1037910386
10387+ function getReducedIntersectionType(type: IntersectionType) {
10388+ const reducedTypes = sameMap(type.types, getReducedType);
10389+ if (reducedTypes === type.types) {
10390+ return type;
10391+ }
10392+ const reduced = getIntersectionType(reducedTypes);
10393+ if (reduced.flags & TypeFlags.Intersection) {
10394+ (<IntersectionType>reduced).resolvedReducedType = reduced;
10395+ }
10396+ return reduced;
10397+ }
10398+
1038010399 function isDiscriminantWithNeverType(prop: Symbol) {
1038110400 return !(prop.flags & SymbolFlags.Optional) &&
1038210401 (getCheckFlags(prop) & (CheckFlags.Discriminant | CheckFlags.HasNeverType)) === CheckFlags.Discriminant &&
@@ -10430,7 +10449,7 @@ namespace ts {
1043010449 * maps primitive types and type parameters are to their apparent types.
1043110450 */
1043210451 function getSignaturesOfType(type: Type, kind: SignatureKind): readonly Signature[] {
10433- return getSignaturesOfStructuredType(getApparentType(getReducedType( type) ), kind);
10452+ return getSignaturesOfStructuredType(getApparentType(type), kind);
1043410453 }
1043510454
1043610455 function getIndexInfoOfStructuredType(type: Type, kind: IndexKind): IndexInfo | undefined {
@@ -10448,13 +10467,13 @@ namespace ts {
1044810467 // Return the indexing info of the given kind in the given type. Creates synthetic union index types when necessary and
1044910468 // maps primitive types and type parameters are to their apparent types.
1045010469 function getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined {
10451- return getIndexInfoOfStructuredType(getApparentType(getReducedType( type) ), kind);
10470+ return getIndexInfoOfStructuredType(getApparentType(type), kind);
1045210471 }
1045310472
1045410473 // Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and
1045510474 // maps primitive types and type parameters are to their apparent types.
1045610475 function getIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined {
10457- return getIndexTypeOfStructuredType(getApparentType(getReducedType( type) ), kind);
10476+ return getIndexTypeOfStructuredType(getApparentType(type), kind);
1045810477 }
1045910478
1046010479 function getImplicitIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined {
@@ -12035,7 +12054,7 @@ namespace ts {
1203512054 }
1203612055 }
1203712056 const objectFlags = (includes & TypeFlags.NotPrimitiveUnion ? 0 : ObjectFlags.PrimitiveUnion) |
12038- (includes & TypeFlags.Intersection ? ObjectFlags.ContainsIntersections : 0);
12057+ (includes & TypeFlags.ReducibleNotUnion ? ObjectFlags.ContainsReducibles : 0);
1203912058 return getUnionTypeFromSortedList(typeSet, objectFlags, aliasSymbol, aliasTypeArguments);
1204012059 }
1204112060
@@ -12750,6 +12769,25 @@ namespace ts {
1275012769 return type[cache] = type;
1275112770 }
1275212771
12772+ function getReducedConditionalType(type: ConditionalType): Type {
12773+ const checkType = type.checkType;
12774+ const extendsType = getInferredExtendsTypeOfConditional(type);
12775+
12776+ if (!isGenericObjectType(checkType) && !isGenericIndexType(checkType) && !isGenericObjectType(extendsType) && !isGenericIndexType(extendsType)) {
12777+ const result = getConditionalSimplificationState(checkType, extendsType);
12778+ switch (result) {
12779+ case ConditionalSimplificationState.True:
12780+ return getReducedType(getInferredTrueTypeFromConditionalType(type));
12781+ case ConditionalSimplificationState.False:
12782+ return getReducedType(getFalseTypeFromConditionalType(type));
12783+ case ConditionalSimplificationState.Both:
12784+ return getUnionType([getReducedType(getInferredTrueTypeFromConditionalType(type)), getReducedType(getFalseTypeFromConditionalType(type))]);
12785+ // None: Fall out and return `type`
12786+ }
12787+ }
12788+ return type;
12789+ }
12790+
1275312791 function getSimplifiedConditionalType(type: ConditionalType, writing: boolean) {
1275412792 const checkType = type.checkType;
1275512793 const extendsType = type.extendsType;
@@ -12821,7 +12859,7 @@ namespace ts {
1282112859 // In the following we resolve T[K] to the type of the property in T selected by K.
1282212860 // We treat boolean as different from other unions to improve errors;
1282312861 // skipping straight to getPropertyTypeForIndexType gives errors with 'boolean' instead of 'true'.
12824- const apparentObjectType = getApparentType(getReducedType( objectType) );
12862+ const apparentObjectType = getApparentType(objectType);
1282512863 if (indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Boolean)) {
1282612864 const propTypes: Type[] = [];
1282712865 let wasMissingProp = false;
@@ -12888,6 +12926,14 @@ namespace ts {
1288812926 return type;
1288912927 }
1289012928
12929+ function isTypeDeferredTypeReference(type: Type) {
12930+ return !!(getObjectFlags(type) & ObjectFlags.Reference) && !!(type as TypeReference).node;
12931+ }
12932+
12933+ function getInferredExtendsTypeOfConditional(type: ConditionalType) {
12934+ return instantiateType(type.root.extendsType, type.combinedMapper || type.mapper);
12935+ }
12936+
1289112937 function getConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined): Type {
1289212938 const checkType = instantiateType(root.checkType, mapper);
1289312939 const extendsType = instantiateType(root.extendsType, mapper);
@@ -12913,28 +12959,17 @@ namespace ts {
1291312959 // Instantiate the extends type including inferences for 'infer T' type parameters
1291412960 const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType;
1291512961 // We attempt to resolve the conditional type only when the check and extends types are non-generic
12916- if (!checkTypeInstantiable && !isGenericObjectType(inferredExtendsType) && !isGenericIndexType(inferredExtendsType)) {
12917- if (inferredExtendsType.flags & TypeFlags.AnyOrUnknown) {
12918- return instantiateType(root.trueType, combinedMapper || mapper);
12919- }
12920- // Return union of trueType and falseType for 'any' since it matches anything
12921- if (checkType.flags & TypeFlags.Any) {
12922- return getUnionType([instantiateType(root.trueType, combinedMapper || mapper), instantiateType(root.falseType, mapper)]);
12923- }
12924- // Return falseType for a definitely false extends check. We check an instantiations of the two
12925- // types with type parameters mapped to the wildcard type, the most permissive instantiations
12926- // possible (the wildcard type is assignable to and from all types). If those are not related,
12927- // then no instantiations will be and we can just return the false branch type.
12928- if (!isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType))) {
12929- return instantiateType(root.falseType, mapper);
12930- }
12931- // Return trueType for a definitely true extends check. We check instantiations of the two
12932- // types with type parameters mapped to their restrictive form, i.e. a form of the type parameter
12933- // that has no constraint. This ensures that, for example, the type
12934- // type Foo<T extends { x: any }> = T extends { x: string } ? string : number
12935- // doesn't immediately resolve to 'string' instead of being deferred.
12936- if (isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(inferredExtendsType))) {
12937- return instantiateType(root.trueType, combinedMapper || mapper);
12962+ if (!checkTypeInstantiable && !isGenericObjectType(inferredExtendsType) && !isGenericIndexType(inferredExtendsType)
12963+ && !isTypeDeferredTypeReference(checkType) && !isTypeDeferredTypeReference(inferredExtendsType)) {
12964+ const result = getConditionalSimplificationState(checkType, inferredExtendsType);
12965+ switch (result) {
12966+ case ConditionalSimplificationState.True:
12967+ return instantiateType(root.trueType, combinedMapper || mapper);
12968+ case ConditionalSimplificationState.Both:
12969+ return getUnionType([instantiateType(root.trueType, combinedMapper || mapper), instantiateType(root.falseType, mapper)]);
12970+ case ConditionalSimplificationState.False:
12971+ return instantiateType(root.falseType, mapper);
12972+ // None: Fall out and defer
1293812973 }
1293912974 }
1294012975 // Return a deferred type for a check that is neither definitely true nor definitely false
@@ -12950,6 +12985,39 @@ namespace ts {
1295012985 return result;
1295112986 }
1295212987
12988+ const enum ConditionalSimplificationState {
12989+ None = 0,
12990+ True = 1,
12991+ False = 2,
12992+ Both = True | False,
12993+ }
12994+
12995+ function getConditionalSimplificationState(checkType: Type, inferredExtendsType: Type): ConditionalSimplificationState {
12996+ if (inferredExtendsType.flags & TypeFlags.AnyOrUnknown) {
12997+ return ConditionalSimplificationState.True;
12998+ }
12999+ // Return union of trueType and falseType for 'any' since it matches anything
13000+ if (checkType.flags & TypeFlags.Any) {
13001+ return ConditionalSimplificationState.Both;
13002+ }
13003+ // Return falseType for a definitely false extends check. We check an instantiations of the two
13004+ // types with type parameters mapped to the wildcard type, the most permissive instantiations
13005+ // possible (the wildcard type is assignable to and from all types). If those are not related,
13006+ // then no instantiations will be and we can just return the false branch type.
13007+ if (!isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType))) {
13008+ return ConditionalSimplificationState.False;
13009+ }
13010+ // Return trueType for a definitely true extends check. We check instantiations of the two
13011+ // types with type parameters mapped to their restrictive form, i.e. a form of the type parameter
13012+ // that has no constraint. This ensures that, for example, the type
13013+ // type Foo<T extends { x: any }> = T extends { x: string } ? string : number
13014+ // doesn't immediately resolve to 'string' instead of being deferred.
13015+ if (isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(inferredExtendsType))) {
13016+ return ConditionalSimplificationState.True;
13017+ }
13018+ return ConditionalSimplificationState.None;
13019+ }
13020+
1295313021 function getTrueTypeFromConditionalType(type: ConditionalType) {
1295413022 return type.resolvedTrueType || (type.resolvedTrueType = instantiateType(type.root.trueType, type.mapper));
1295513023 }
@@ -14986,7 +15054,7 @@ namespace ts {
1498615054 while (true) {
1498715055 const t = isFreshLiteralType(type) ? (<FreshableType>type).regularType :
1498815056 getObjectFlags(type) & ObjectFlags.Reference && (<TypeReference>type).node ? createTypeReference((<TypeReference>type).target, getTypeArguments(<TypeReference>type)) :
14989- type.flags & TypeFlags.UnionOrIntersection ? getReducedType(type) :
15057+ type.flags & TypeFlags.Reducible ? getSimplifiedType( getReducedType(type), writing ) :
1499015058 type.flags & TypeFlags.Substitution ? writing ? (<SubstitutionType>type).baseType : (<SubstitutionType>type).substitute :
1499115059 type.flags & TypeFlags.Simplifiable ? getSimplifiedType(type, writing) :
1499215060 type;
0 commit comments