@@ -14259,7 +14259,7 @@ namespace ts {
14259
14259
}
14260
14260
}
14261
14261
14262
- function forEachMatchingParameterType (source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
14262
+ function applyToParameterTypes (source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
14263
14263
const sourceCount = getParameterCount(source);
14264
14264
const targetCount = getParameterCount(target);
14265
14265
const sourceRestType = getEffectiveRestType(source);
@@ -14281,6 +14281,18 @@ namespace ts {
14281
14281
}
14282
14282
}
14283
14283
14284
+ function applyToReturnTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
14285
+ const sourceTypePredicate = getTypePredicateOfSignature(source);
14286
+ const targetTypePredicate = getTypePredicateOfSignature(target);
14287
+ if (sourceTypePredicate && targetTypePredicate && sourceTypePredicate.kind === targetTypePredicate.kind &&
14288
+ (sourceTypePredicate.kind === TypePredicateKind.This || sourceTypePredicate.parameterIndex === (<IdentifierTypePredicate>targetTypePredicate).parameterIndex)) {
14289
+ callback(sourceTypePredicate.type, targetTypePredicate.type);
14290
+ }
14291
+ else {
14292
+ callback(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
14293
+ }
14294
+ }
14295
+
14284
14296
function createInferenceContext(typeParameters: ReadonlyArray<TypeParameter>, signature: Signature | undefined, flags: InferenceFlags, compareTypes?: TypeComparer): InferenceContext {
14285
14297
return createInferenceContextWorker(typeParameters.map(createInferenceInfo), signature, flags, compareTypes || compareTypesAssignable);
14286
14298
}
@@ -14900,17 +14912,10 @@ namespace ts {
14900
14912
const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown;
14901
14913
// Once we descend into a bivariant signature we remain bivariant for all nested inferences
14902
14914
bivariant = bivariant || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.MethodSignature || kind === SyntaxKind.Constructor;
14903
- forEachMatchingParameterType (source, target, inferFromContravariantTypes);
14915
+ applyToParameterTypes (source, target, inferFromContravariantTypes);
14904
14916
bivariant = saveBivariant;
14905
14917
}
14906
- const sourceTypePredicate = getTypePredicateOfSignature(source);
14907
- const targetTypePredicate = getTypePredicateOfSignature(target);
14908
- if (sourceTypePredicate && targetTypePredicate && sourceTypePredicate.kind === targetTypePredicate.kind) {
14909
- inferFromTypes(sourceTypePredicate.type, targetTypePredicate.type);
14910
- }
14911
- else {
14912
- inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
14913
- }
14918
+ applyToReturnTypes(source, target, inferFromTypes);
14914
14919
}
14915
14920
14916
14921
function inferFromIndexTypes(source: Type, target: Type) {
@@ -20137,18 +20142,14 @@ namespace ts {
20137
20142
const restType = getEffectiveRestType(contextualSignature);
20138
20143
const mapper = inferenceContext && (restType && restType.flags & TypeFlags.TypeParameter ? inferenceContext.nonFixingMapper : inferenceContext.mapper);
20139
20144
const sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature;
20140
- forEachMatchingParameterType (sourceSignature, signature, (source, target) => {
20145
+ applyToParameterTypes (sourceSignature, signature, (source, target) => {
20141
20146
// Type parameters from outer context referenced by source type are fixed by instantiation of the source type
20142
20147
inferTypes(context.inferences, source, target);
20143
20148
});
20144
20149
if (!inferenceContext) {
20145
- inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), InferencePriority.ReturnType);
20146
- const signaturePredicate = getTypePredicateOfSignature(signature);
20147
- const contextualPredicate = getTypePredicateOfSignature(sourceSignature);
20148
- if (signaturePredicate && contextualPredicate && signaturePredicate.kind === contextualPredicate.kind &&
20149
- (signaturePredicate.kind === TypePredicateKind.This || signaturePredicate.parameterIndex === (contextualPredicate as IdentifierTypePredicate).parameterIndex)) {
20150
- inferTypes(context.inferences, contextualPredicate.type, signaturePredicate.type, InferencePriority.ReturnType);
20151
- }
20150
+ applyToReturnTypes(contextualSignature, signature, (source, target) => {
20151
+ inferTypes(context.inferences, source, target, InferencePriority.ReturnType);
20152
+ });
20152
20153
}
20153
20154
return getSignatureInstantiation(signature, getInferredTypes(context), isInJSFile(contextualSignature.declaration));
20154
20155
}
@@ -23465,23 +23466,30 @@ namespace ts {
23465
23466
// potentially add inferred type parameters to the outer function return type.
23466
23467
const returnSignature = context.signature && getSingleCallSignature(getReturnTypeOfSignature(context.signature));
23467
23468
if (returnSignature && !returnSignature.typeParameters && !every(context.inferences, hasInferenceCandidates)) {
23468
- // Instantiate the expression type with its own type parameters as type arguments. This
23469
- // ensures that the type parameters are not erased to type any during type inference such
23470
- // that they can be inferred as actual types.
23469
+ // Instantiate the signature with its own type parameters as type arguments, possibly
23470
+ // renaming the type parameters to ensure they have unique names.
23471
23471
const uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters);
23472
- const strippedType = getOrCreateTypeFromSignature( getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters) );
23473
- // Infer from the stripped expression type to the contextual type starting with an empty
23474
- // set of inference candidates.
23472
+ const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters);
23473
+ // Infer from the parameters of the instantiated signature to the parameters of the
23474
+ // contextual signature starting with an empty set of inference candidates.
23475
23475
const inferences = map(context.inferences, info => createInferenceInfo(info.typeParameter));
23476
- inferTypes(inferences, strippedType, contextualType);
23477
- // If we produced some inference candidates and if the type parameters for which we produced
23478
- // candidates do not already have existing inferences, we adopt the new inference candidates and
23479
- // add the type parameters of the expression type to the set of inferred type parameters for
23480
- // the outer function return type.
23481
- if (some(inferences, hasInferenceCandidates) && !hasOverlappingInferences(context.inferences, inferences)) {
23482
- mergeInferences(context.inferences, inferences);
23483
- context.inferredTypeParameters = concatenate(context.inferredTypeParameters, uniqueTypeParameters);
23484
- return strippedType;
23476
+ applyToParameterTypes(instantiatedSignature, contextualSignature, (source, target) => {
23477
+ inferTypes(inferences, source, target);
23478
+ });
23479
+ if (some(inferences, hasInferenceCandidates)) {
23480
+ // We have inference candidates, indicating that one or more type parameters are referenced
23481
+ // in the parameter types of the contextual signature. Now also infer from the return type.
23482
+ applyToReturnTypes(instantiatedSignature, contextualSignature, (source, target) => {
23483
+ inferTypes(inferences, source, target);
23484
+ });
23485
+ // If the type parameters for which we produced candidates do not have any inferences yet,
23486
+ // we adopt the new inference candidates and add the type parameters of the expression type
23487
+ // to the set of inferred type parameters for the outer function return type.
23488
+ if (!hasOverlappingInferences(context.inferences, inferences)) {
23489
+ mergeInferences(context.inferences, inferences);
23490
+ context.inferredTypeParameters = concatenate(context.inferredTypeParameters, uniqueTypeParameters);
23491
+ return getOrCreateTypeFromSignature(instantiatedSignature);
23492
+ }
23485
23493
}
23486
23494
}
23487
23495
return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context));
0 commit comments