Skip to content

Commit bf5b762

Browse files
committed
Merge overloads that only differ by return type when intersecting.
1 parent 2932421 commit bf5b762

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

src/compiler/checker.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7087,13 +7087,49 @@ namespace ts {
70877087
}
70887088
constructSignatures = concatenate(constructSignatures, signatures);
70897089
}
7090+
70907091
callSignatures = concatenate(callSignatures, getSignaturesOfType(t, SignatureKind.Call));
70917092
stringIndexInfo = intersectIndexInfos(stringIndexInfo, getIndexInfoOfType(t, IndexKind.String));
70927093
numberIndexInfo = intersectIndexInfos(numberIndexInfo, getIndexInfoOfType(t, IndexKind.Number));
70937094
}
7095+
7096+
callSignatures = intersectCallSignatures(callSignatures);
7097+
70947098
setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
70957099
}
70967100

7101+
function intersectCallSignatures(callSignatures: ReadonlyArray<Signature>): ReadonlyArray<Signature> {
7102+
// Overloads that differ only be return type make no sense. So:
7103+
// 1. Group all the call signatures by their parameter types. Each group is an overload.
7104+
// 2. Create a new signature for each group where the return type is the intersection
7105+
// of the return types of the signatures in that group.
7106+
const groups: Signature[][] = [];
7107+
7108+
callSignatures.forEach((callSignature) => {
7109+
const matchingGroup = find(groups, (group) => {
7110+
const candidate = group[0];
7111+
const candidateParameters = candidate.parameters;
7112+
const thisCallParameters = callSignature.parameters;
7113+
return candidateParameters.length === thisCallParameters.length &&
7114+
every(thisCallParameters, (parameter, index) => isTypeIdenticalTo(getTypeOfParameter(parameter), getTypeOfParameter(candidateParameters[index])));
7115+
});
7116+
if (matchingGroup === undefined) {
7117+
groups.push([callSignature]);
7118+
} else {
7119+
matchingGroup.push(callSignature);
7120+
}
7121+
});
7122+
7123+
return groups.map((signatures) => {
7124+
if (signatures.length === 1) {
7125+
return signatures[0];
7126+
}
7127+
const clone = cloneSignature(signatures[0]);
7128+
clone.resolvedReturnType = getIntersectionType(signatures.map(signature => getReturnTypeOfSignature(signature)));
7129+
return clone;
7130+
});
7131+
}
7132+
70977133
/**
70987134
* Converts an AnonymousType to a ResolvedType.
70997135
*/

0 commit comments

Comments
 (0)