@@ -7587,9 +7587,52 @@ namespace ts {
7587
7587
function getTypeFromTypeCall(type: TypeCallType, node: TypeCallTypeNode): Type {
7588
7588
const fn = type.function;
7589
7589
const args = type.arguments;
7590
- const calls = getSignaturesOfType(fn, SignatureKind.Call);
7591
- const sig = resolveCall(node, calls, /*candidatesOutArray*/ [], /*fallBackError*/ undefined, args);
7592
- return sig ? getReturnTypeOfSignature(sig) : unknownType;
7590
+ const candidates = getSignaturesOfType(fn, SignatureKind.Call);
7591
+ const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters;
7592
+ if (isSingleNonGenericCandidate) {
7593
+ const sig = resolveCall(node, candidates, /*candidatesOutArray*/ [], /*fallBackError*/ undefined, args);
7594
+ return sig ? getReturnTypeOfSignature(sig) : unknownType;
7595
+ }
7596
+ else {
7597
+ // we have unions and they matter -- separately calculate the result for each permutation
7598
+ const types: Type[] = [];
7599
+ const indices: number[] = map(args, (tp: Type, i: number) => tp.flags & TypeFlags.Union &&
7600
+ some(candidates, (sig: Signature) => isGenericObjectType(getTypeAtPosition(sig, i))) ?
7601
+ // ^ future consideration: argument/parameter i correspondence breaks down with tuple spreads
7602
+ 0 : undefined);
7603
+ const argTypes: Array<Type[] | Type> = map(args, (tp: Type, i: number) => indices[i] !== undefined ? (<UnionType>tp).types : tp);
7604
+ checkParams: while (true) {
7605
+ const myArgs = map(argTypes, (tp: Type[] | Type, i: number) => {
7606
+ const argIdx = indices[i];
7607
+ return argIdx === undefined ? <Type>tp : (<Type[]>tp)[argIdx];
7608
+ });
7609
+ const sig = resolveCall(node, candidates, /*candidatesOutArray*/ [], /*fallBackError*/ undefined, myArgs);
7610
+ if (sig) {
7611
+ types.push(getReturnTypeOfSignature(sig));
7612
+ }
7613
+ // increment the next index to try the next permutation
7614
+ for (let i = 0; i < indices.length; i++) {
7615
+ const idx = indices[i];
7616
+ if (idx === undefined) {
7617
+ // nothing to do here, try switching the next argument
7618
+ continue;
7619
+ }
7620
+ else if (idx < (<Type[]>argTypes[i]).length - 1) {
7621
+ // can increment without overflow
7622
+ indices[i] = indices[i] + 1;
7623
+ continue checkParams;
7624
+ }
7625
+ else {
7626
+ // overflow, try switching the next argument as well
7627
+ indices[i] = 0;
7628
+ continue;
7629
+ }
7630
+ }
7631
+ // all options tried, full overflow throughout for-loop, done
7632
+ break;
7633
+ }
7634
+ return getUnionType(types);
7635
+ }
7593
7636
}
7594
7637
7595
7638
function getTypeFromTypeCallNode(node: TypeCallTypeNode): Type {
0 commit comments