@@ -7900,6 +7900,7 @@ namespace ts {
7900
7900
}
7901
7901
else if (flags & TypeFlags.Any) {
7902
7902
includes |= TypeIncludes.Any;
7903
+ if (type === wildcardType) includes |= TypeIncludes.Wildcard;
7903
7904
}
7904
7905
else if (flags & TypeFlags.Never) {
7905
7906
includes |= TypeIncludes.Never;
@@ -7951,7 +7952,7 @@ namespace ts {
7951
7952
return neverType;
7952
7953
}
7953
7954
if (includes & TypeIncludes.Any) {
7954
- return anyType;
7955
+ return includes & TypeIncludes.Wildcard ? wildcardType : anyType;
7955
7956
}
7956
7957
if (includes & TypeIncludes.EmptyObject && !(includes & TypeIncludes.ObjectType)) {
7957
7958
typeSet.push(emptyObjectType);
@@ -8189,6 +8190,9 @@ namespace ts {
8189
8190
}
8190
8191
8191
8192
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode): Type {
8193
+ if (objectType === wildcardType || indexType === wildcardType) {
8194
+ return wildcardType;
8195
+ }
8192
8196
// If the index type is generic, or if the object type is generic and doesn't originate in an expression,
8193
8197
// we are performing a higher-order index access where we cannot meaningfully access the properties of the
8194
8198
// object type. Note that for a generic T and a non-generic K, we eagerly resolve T[K] if it originates in
@@ -8254,37 +8258,45 @@ namespace ts {
8254
8258
function getConditionalType(root: ConditionalRoot, mapper: TypeMapper): Type {
8255
8259
const checkType = instantiateType(root.checkType, mapper);
8256
8260
const extendsType = instantiateType(root.extendsType, mapper);
8257
- // Return falseType for a definitely false extends check. We check an instantations of the two
8258
- // types with type parameters mapped to the wildcard type, the most permissive instantiations
8259
- // possible (the wildcard type is assignable to and from all types). If those are not related,
8260
- // then no instatiations will be and we can just return the false branch type.
8261
- if (!typeMaybeAssignableTo(getWildcardInstantiation(checkType), getWildcardInstantiation(extendsType))) {
8262
- return instantiateType(root.falseType, mapper);
8263
- }
8264
- // The check could be true for some instantiation
8265
- let combinedMapper: TypeMapper;
8266
- if (root.inferTypeParameters) {
8267
- const inferences = map(root.inferTypeParameters, createInferenceInfo);
8268
- // We don't want inferences from constraints as they may cause us to eagerly resolve the
8269
- // conditional type instead of deferring resolution. Also, we always want strict function
8270
- // types rules (i.e. proper contravariance) for inferences.
8271
- inferTypes(inferences, checkType, extendsType, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict);
8272
- // We infer {} when there are no candidates for a type parameter
8273
- const inferredTypes = map(inferences, inference => getTypeFromInference(inference) || emptyObjectType);
8274
- combinedMapper = combineTypeMappers(mapper, createTypeMapper(root.inferTypeParameters, inferredTypes));
8275
- }
8276
- // Return union of trueType and falseType for 'any' since it matches anything
8277
- if (checkType.flags & TypeFlags.Any) {
8278
- return getUnionType([instantiateType(root.trueType, combinedMapper || mapper), instantiateType(root.falseType, mapper)]);
8279
- }
8280
- // Instantiate the extends type including inferences for 'infer T' type parameters
8281
- const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType;
8282
- // Return trueType for a definitely true extends check. The definitely assignable relation excludes
8283
- // type variable constraints from consideration. Without the definitely assignable relation, the type
8284
- // type Foo<T extends { x: any }> = T extends { x: string } ? string : number
8285
- // would immediately resolve to 'string' instead of being deferred.
8286
- if (checkTypeRelatedTo(checkType, inferredExtendsType, definitelyAssignableRelation, /*errorNode*/ undefined)) {
8287
- return instantiateType(root.trueType, combinedMapper || mapper);
8261
+ if (checkType === wildcardType || extendsType === wildcardType) {
8262
+ return wildcardType;
8263
+ }
8264
+ // If this is a distributive conditional type and the check type is generic, we need to defer
8265
+ // resolution of the conditional type such that a later instantiation will properly distribute
8266
+ // over union types.
8267
+ if (!root.isDistributive || !maybeTypeOfKind(checkType, TypeFlags.Instantiable)) {
8268
+ // Return falseType for a definitely false extends check. We check an instantations of the two
8269
+ // types with type parameters mapped to the wildcard type, the most permissive instantiations
8270
+ // possible (the wildcard type is assignable to and from all types). If those are not related,
8271
+ // then no instatiations will be and we can just return the false branch type.
8272
+ if (!isTypeAssignableTo(getWildcardInstantiation(checkType), getWildcardInstantiation(extendsType))) {
8273
+ return instantiateType(root.falseType, mapper);
8274
+ }
8275
+ // The check could be true for some instantiation
8276
+ let combinedMapper: TypeMapper;
8277
+ if (root.inferTypeParameters) {
8278
+ const inferences = map(root.inferTypeParameters, createInferenceInfo);
8279
+ // We don't want inferences from constraints as they may cause us to eagerly resolve the
8280
+ // conditional type instead of deferring resolution. Also, we always want strict function
8281
+ // types rules (i.e. proper contravariance) for inferences.
8282
+ inferTypes(inferences, checkType, extendsType, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict);
8283
+ // We infer {} when there are no candidates for a type parameter
8284
+ const inferredTypes = map(inferences, inference => getTypeFromInference(inference) || emptyObjectType);
8285
+ combinedMapper = combineTypeMappers(mapper, createTypeMapper(root.inferTypeParameters, inferredTypes));
8286
+ }
8287
+ // Return union of trueType and falseType for 'any' since it matches anything
8288
+ if (checkType.flags & TypeFlags.Any) {
8289
+ return getUnionType([instantiateType(root.trueType, combinedMapper || mapper), instantiateType(root.falseType, mapper)]);
8290
+ }
8291
+ // Instantiate the extends type including inferences for 'infer T' type parameters
8292
+ const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType;
8293
+ // Return trueType for a definitely true extends check. The definitely assignable relation excludes
8294
+ // type variable constraints from consideration. Without the definitely assignable relation, the type
8295
+ // type Foo<T extends { x: any }> = T extends { x: string } ? string : number
8296
+ // would immediately resolve to 'string' instead of being deferred.
8297
+ if (checkTypeRelatedTo(checkType, inferredExtendsType, definitelyAssignableRelation, /*errorNode*/ undefined)) {
8298
+ return instantiateType(root.trueType, combinedMapper || mapper);
8299
+ }
8288
8300
}
8289
8301
// Return a deferred type for a check that is neither definitely true nor definitely false
8290
8302
const erasedCheckType = getActualTypeParameter(checkType);
0 commit comments