@@ -25154,22 +25154,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
25154
25154
const inference = context.inferences[index];
25155
25155
if (!inference.inferredType) {
25156
25156
let inferredType: Type | undefined;
25157
- const signature = context.signature;
25158
- if (signature) {
25159
- const inferredCovariantType = inference.candidates ? getCovariantInference(inference, signature) : undefined;
25160
- if (inference.contraCandidates) {
25161
- // If we have both co- and contra-variant inferences, we use the co-variant inference if it is not 'never',
25162
- // it is a subtype of some contra-variant inference, and no other type parameter is constrained to this type
25163
- // parameter and has inferences that would conflict. Otherwise, we use the contra-variant inference.
25164
- const useCovariantType = inferredCovariantType && !(inferredCovariantType.flags & TypeFlags.Never) &&
25157
+ let fallbackType: Type | undefined;
25158
+ if (context.signature) {
25159
+ const inferredCovariantType = inference.candidates ? getCovariantInference(inference, context.signature) : undefined;
25160
+ const inferredContravariantType = inference.contraCandidates ? getContravariantInference(inference) : undefined;
25161
+ if (inferredCovariantType || inferredContravariantType) {
25162
+ // If we have both co- and contra-variant inferences, we prefer the co-variant inference if it is not 'never',
25163
+ // all co-variant inferences are subtypes of it (i.e. it isn't one of a conflicting set of candidates), it is
25164
+ // a subtype of some contra-variant inference, and no other type parameter is constrained to this type parameter
25165
+ // and has inferences that would conflict. Otherwise, we prefer the contra-variant inference.
25166
+ const preferCovariantType = inferredCovariantType && (!inferredContravariantType ||
25167
+ !(inferredCovariantType.flags & TypeFlags.Never) &&
25168
+ every(inference.candidates, t => isTypeSubtypeOf(t, inferredCovariantType)) &&
25165
25169
some(inference.contraCandidates, t => isTypeSubtypeOf(inferredCovariantType, t)) &&
25166
- every(context.inferences, other =>
25167
- other !== inference && getConstraintOfTypeParameter(other.typeParameter) !== inference.typeParameter ||
25168
- every(other.candidates, t => isTypeSubtypeOf(t, inferredCovariantType)));
25169
- inferredType = useCovariantType ? inferredCovariantType : getContravariantInference(inference);
25170
- }
25171
- else if (inferredCovariantType) {
25172
- inferredType = inferredCovariantType;
25170
+ every(context.inferences, other => other === inference ||
25171
+ getConstraintOfTypeParameter(other.typeParameter) !== inference.typeParameter ||
25172
+ every(other.candidates, t => isTypeSubtypeOf(t, inferredCovariantType))));
25173
+ inferredType = preferCovariantType ? inferredCovariantType : inferredContravariantType;
25174
+ fallbackType = preferCovariantType ? inferredContravariantType : inferredCovariantType;
25173
25175
}
25174
25176
else if (context.flags & InferenceFlags.NoDefault) {
25175
25177
// We use silentNeverType as the wildcard that signals no inferences.
@@ -25199,7 +25201,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
25199
25201
if (constraint) {
25200
25202
const instantiatedConstraint = instantiateType(constraint, context.nonFixingMapper);
25201
25203
if (!inferredType || !context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
25202
- inference.inferredType = inferredType = instantiatedConstraint;
25204
+ // If the fallback type satisfies the constraint, we pick it. Otherwise, we pick the constraint.
25205
+ inference.inferredType = fallbackType && context.compareTypes(fallbackType, getTypeWithThisArgument(instantiatedConstraint, fallbackType)) ? fallbackType : instantiatedConstraint;
25203
25206
}
25204
25207
}
25205
25208
}
0 commit comments