@@ -7521,7 +7521,7 @@ namespace ts {
7521
7521
return {
7522
7522
primary: undefined,
7523
7523
secondary: undefined,
7524
- shallow : true,
7524
+ topLevel : true,
7525
7525
isFixed: false,
7526
7526
};
7527
7527
}
@@ -7543,14 +7543,18 @@ namespace ts {
7543
7543
return type.couldContainTypeParameters;
7544
7544
}
7545
7545
7546
- function inferTypes(context: InferenceContext, source: Type, target: Type) {
7546
+ function isTypeParameterAtTopLevel(type: Type, typeParameter: TypeParameter): boolean {
7547
+ return type === typeParameter || type.flags & TypeFlags.UnionOrIntersection && forEach((<UnionOrIntersectionType>type).types, t => isTypeParameterAtTopLevel(t, typeParameter));
7548
+ }
7549
+
7550
+ function inferTypes(context: InferenceContext, originalSource: Type, originalTarget: Type) {
7547
7551
const typeParameters = context.signature.typeParameters;
7548
7552
let sourceStack: Type[];
7549
7553
let targetStack: Type[];
7550
7554
let depth = 0;
7551
7555
let inferiority = 0;
7552
7556
const visited = createMap<boolean>();
7553
- inferFromTypes(source, target, /*nested*/ false );
7557
+ inferFromTypes(originalSource, originalTarget );
7554
7558
7555
7559
function isInProcess(source: Type, target: Type) {
7556
7560
for (let i = 0; i < depth; i++) {
@@ -7561,7 +7565,7 @@ namespace ts {
7561
7565
return false;
7562
7566
}
7563
7567
7564
- function inferFromTypes(source: Type, target: Type, nested: boolean ) {
7568
+ function inferFromTypes(source: Type, target: Type) {
7565
7569
if (!couldContainTypeParameters(target)) {
7566
7570
return;
7567
7571
}
@@ -7571,7 +7575,7 @@ namespace ts {
7571
7575
// are the same type, just relate each constituent type to itself.
7572
7576
if (source === target) {
7573
7577
for (const t of (<UnionOrIntersectionType>source).types) {
7574
- inferFromTypes(t, t, /*nested*/ false );
7578
+ inferFromTypes(t, t);
7575
7579
}
7576
7580
return;
7577
7581
}
@@ -7583,7 +7587,7 @@ namespace ts {
7583
7587
for (const t of (<UnionOrIntersectionType>target).types) {
7584
7588
if (typeIdenticalToSomeType(t, (<UnionOrIntersectionType>source).types)) {
7585
7589
(matchingTypes || (matchingTypes = [])).push(t);
7586
- inferFromTypes(t, t, /*nested*/ false );
7590
+ inferFromTypes(t, t);
7587
7591
}
7588
7592
}
7589
7593
// Next, to improve the quality of inferences, reduce the source and target types by
@@ -7620,8 +7624,8 @@ namespace ts {
7620
7624
if (!contains(candidates, source)) {
7621
7625
candidates.push(source);
7622
7626
}
7623
- if (nested ) {
7624
- inferences.shallow = false;
7627
+ if (!isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target) ) {
7628
+ inferences.topLevel = false;
7625
7629
}
7626
7630
}
7627
7631
return;
@@ -7634,7 +7638,7 @@ namespace ts {
7634
7638
const targetTypes = (<TypeReference>target).typeArguments || emptyArray;
7635
7639
const count = sourceTypes.length < targetTypes.length ? sourceTypes.length : targetTypes.length;
7636
7640
for (let i = 0; i < count; i++) {
7637
- inferFromTypes(sourceTypes[i], targetTypes[i], /*nested*/ true );
7641
+ inferFromTypes(sourceTypes[i], targetTypes[i]);
7638
7642
}
7639
7643
}
7640
7644
else if (target.flags & TypeFlags.UnionOrIntersection) {
@@ -7648,23 +7652,23 @@ namespace ts {
7648
7652
typeParameterCount++;
7649
7653
}
7650
7654
else {
7651
- inferFromTypes(source, t, /*nested*/ false );
7655
+ inferFromTypes(source, t);
7652
7656
}
7653
7657
}
7654
7658
// Next, if target containings a single naked type parameter, make a secondary inference to that type
7655
7659
// parameter. This gives meaningful results for union types in co-variant positions and intersection
7656
7660
// types in contra-variant positions (such as callback parameters).
7657
7661
if (typeParameterCount === 1) {
7658
7662
inferiority++;
7659
- inferFromTypes(source, typeParameter, /*nested*/ false );
7663
+ inferFromTypes(source, typeParameter);
7660
7664
inferiority--;
7661
7665
}
7662
7666
}
7663
7667
else if (source.flags & TypeFlags.UnionOrIntersection) {
7664
7668
// Source is a union or intersection type, infer from each constituent type
7665
7669
const sourceTypes = (<UnionOrIntersectionType>source).types;
7666
7670
for (const sourceType of sourceTypes) {
7667
- inferFromTypes(sourceType, target, /*nested*/ false );
7671
+ inferFromTypes(sourceType, target);
7668
7672
}
7669
7673
}
7670
7674
else {
@@ -7702,7 +7706,7 @@ namespace ts {
7702
7706
for (const targetProp of properties) {
7703
7707
const sourceProp = getPropertyOfObjectType(source, targetProp.name);
7704
7708
if (sourceProp) {
7705
- inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp), /*nested*/ true );
7709
+ inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
7706
7710
}
7707
7711
}
7708
7712
}
@@ -7719,17 +7723,17 @@ namespace ts {
7719
7723
}
7720
7724
7721
7725
function inferFromParameterTypes(source: Type, target: Type) {
7722
- return inferFromTypes(source, target, /*nested*/ true );
7726
+ return inferFromTypes(source, target);
7723
7727
}
7724
7728
7725
7729
function inferFromSignature(source: Signature, target: Signature) {
7726
7730
forEachMatchingParameterType(source, target, inferFromParameterTypes);
7727
7731
7728
7732
if (source.typePredicate && target.typePredicate && source.typePredicate.kind === target.typePredicate.kind) {
7729
- inferFromTypes(source.typePredicate.type, target.typePredicate.type, /*nested*/ true );
7733
+ inferFromTypes(source.typePredicate.type, target.typePredicate.type);
7730
7734
}
7731
7735
else {
7732
- inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target), /*nested*/ true );
7736
+ inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
7733
7737
}
7734
7738
}
7735
7739
@@ -7739,7 +7743,7 @@ namespace ts {
7739
7743
const sourceIndexType = getIndexTypeOfType(source, IndexKind.String) ||
7740
7744
getImplicitIndexTypeOfType(source, IndexKind.String);
7741
7745
if (sourceIndexType) {
7742
- inferFromTypes(sourceIndexType, targetStringIndexType, /*nested*/ true );
7746
+ inferFromTypes(sourceIndexType, targetStringIndexType);
7743
7747
}
7744
7748
}
7745
7749
const targetNumberIndexType = getIndexTypeOfType(target, IndexKind.Number);
@@ -7748,7 +7752,7 @@ namespace ts {
7748
7752
getIndexTypeOfType(source, IndexKind.String) ||
7749
7753
getImplicitIndexTypeOfType(source, IndexKind.Number);
7750
7754
if (sourceIndexType) {
7751
- inferFromTypes(sourceIndexType, targetNumberIndexType, /*nested*/ true );
7755
+ inferFromTypes(sourceIndexType, targetNumberIndexType);
7752
7756
}
7753
7757
}
7754
7758
}
@@ -7787,25 +7791,20 @@ namespace ts {
7787
7791
return constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive);
7788
7792
}
7789
7793
7790
- function hasTypeParameterAtTopLevel(type: Type, typeParameter: TypeParameter): boolean {
7791
- return type === typeParameter || type.flags & TypeFlags.UnionOrIntersection && forEach((<UnionOrIntersectionType>type).types, t => hasTypeParameterAtTopLevel(t, typeParameter));
7792
- }
7793
-
7794
-
7795
7794
function getInferredType(context: InferenceContext, index: number): Type {
7796
7795
let inferredType = context.inferredTypes[index];
7797
7796
let inferenceSucceeded: boolean;
7798
7797
if (!inferredType) {
7799
7798
const inferences = getInferenceCandidates(context, index);
7800
7799
if (inferences.length) {
7801
- // We keep inferences of literal types if
7802
- // we made at least one inference that wasn't shallow, or
7803
- // the type parameter has a primitive type constraint, or
7804
- // the type parameter wasn't fixed and is referenced at top level in the return type.
7800
+ // We widen inferred literal types if
7801
+ // all inferences were made to top-level ocurrences of the type parameter, and
7802
+ // the type parameter has no constraint or its constraint includes no primitive or literal types, and
7803
+ // the type parameter was fixed during inference or does not occur at top- level in the return type.
7805
7804
const signature = context.signature;
7806
- const widenLiteralTypes = context.inferences[index].shallow &&
7805
+ const widenLiteralTypes = context.inferences[index].topLevel &&
7807
7806
!hasPrimitiveConstraint(signature.typeParameters[index]) &&
7808
- (context.inferences[index].isFixed || !hasTypeParameterAtTopLevel (getReturnTypeOfSignature(signature), signature.typeParameters[index]));
7807
+ (context.inferences[index].isFixed || !isTypeParameterAtTopLevel (getReturnTypeOfSignature(signature), signature.typeParameters[index]));
7809
7808
const baseInferences = widenLiteralTypes ? map(inferences, getBaseTypeOfLiteralType) : inferences;
7810
7809
// Infer widened union or supertype, or the unknown type for no common supertype
7811
7810
const unionOrSuperType = context.inferUnionTypes ? getUnionType(baseInferences, /*subtypeReduction*/ true) : getCommonSupertype(baseInferences);
0 commit comments