@@ -15568,42 +15568,45 @@ namespace ts {
1556815568 return;
1556915569 }
1557015570 if (target.flags & TypeFlags.Union) {
15571- if (source.flags & TypeFlags.Union) {
15572- // First, infer between identically matching source and target constituents and remove the
15573- // matching types.
15574- const [tempSources, tempTargets] = inferFromMatchingTypes((<UnionType>source).types, (<UnionType>target).types, isTypeOrBaseIdenticalTo);
15575- // Next, infer between closely matching source and target constituents and remove
15576- // the matching types. Types closely match when they are instantiations of the same
15577- // object type or instantiations of the same type alias.
15578- const [sources, targets] = inferFromMatchingTypes(tempSources, tempTargets, isTypeCloselyMatchedBy);
15579- if (sources.length === 0 || targets.length === 0) {
15580- return;
15581- }
15582- source = getUnionType(sources);
15583- target = getUnionType(targets);
15571+ // First, infer between identically matching source and target constituents and remove the
15572+ // matching types.
15573+ const [tempSources, tempTargets] = inferFromMatchingTypes(source.flags & TypeFlags.Union ? (<UnionType>source).types : [source], (<UnionType>target).types, isTypeOrBaseIdenticalTo);
15574+ // Next, infer between closely matching source and target constituents and remove
15575+ // the matching types. Types closely match when they are instantiations of the same
15576+ // object type or instantiations of the same type alias.
15577+ const [sources, targets] = inferFromMatchingTypes(tempSources, tempTargets, isTypeCloselyMatchedBy);
15578+ if (targets.length === 0) {
15579+ return;
1558415580 }
15585- else {
15586- if (inferFromMatchingType(source, (<UnionType>target).types, isTypeOrBaseIdenticalTo)) return;
15587- if (inferFromMatchingType(source, (<UnionType>target).types, isTypeCloselyMatchedBy)) return;
15581+ target = getUnionType(targets);
15582+ if (sources.length === 0) {
15583+ // All source constituents have been matched and there is nothing further to infer from.
15584+ // However, simply making no inferences is undesirable because it could ultimately mean
15585+ // inferring a type parameter constraint. Instead, make a lower priority inference from
15586+ // the full source to whatever remains in the target. For example, when inferring from
15587+ // string to 'string | T', make a lower priority inference of string for T.
15588+ const savePriority = priority;
15589+ priority |= InferencePriority.NakedTypeVariable;
15590+ inferFromTypes(source, target);
15591+ priority = savePriority;
15592+ return;
1558815593 }
15594+ source = getUnionType(sources);
1558915595 }
1559015596 else if (target.flags & TypeFlags.Intersection && some((<IntersectionType>target).types, t => !!getInferenceInfoForType(t))) {
1559115597 // We reduce intersection types only when they contain naked type parameters. For example, when
1559215598 // inferring from 'string[] & { extra: any }' to 'string[] & T' we want to remove string[] and
1559315599 // infer { extra: any } for T. But when inferring to 'string[] & Iterable<T>' we want to keep the
1559415600 // string[] on the source side and infer string for T.
15595- if (source.flags & TypeFlags.Intersection ) {
15601+ if (!( source.flags & TypeFlags.Union) ) {
1559615602 // Infer between identically matching source and target constituents and remove the matching types.
15597- const [sources, targets] = inferFromMatchingTypes((<IntersectionType>source).types, (<IntersectionType>target).types, isTypeIdenticalTo);
15603+ const [sources, targets] = inferFromMatchingTypes(source.flags & TypeFlags.Intersection ? (<IntersectionType>source).types : [source] , (<IntersectionType>target).types, isTypeIdenticalTo);
1559815604 if (sources.length === 0 || targets.length === 0) {
1559915605 return;
1560015606 }
1560115607 source = getIntersectionType(sources);
1560215608 target = getIntersectionType(targets);
1560315609 }
15604- else if (!(source.flags & TypeFlags.Union)) {
15605- if (inferFromMatchingType(source, (<IntersectionType>target).types, isTypeIdenticalTo)) return;
15606- }
1560715610 }
1560815611 else if (target.flags & (TypeFlags.IndexedAccess | TypeFlags.Substitution)) {
1560915612 target = getActualTypeVariable(target);
@@ -15753,17 +15756,6 @@ namespace ts {
1575315756 inferencePriority = Math.min(inferencePriority, saveInferencePriority);
1575415757 }
1575515758
15756- function inferFromMatchingType(source: Type, targets: Type[], matches: (s: Type, t: Type) => boolean) {
15757- let matched = false;
15758- for (const t of targets) {
15759- if (matches(source, t)) {
15760- inferFromTypes(source, t);
15761- matched = true;
15762- }
15763- }
15764- return matched;
15765- }
15766-
1576715759 function inferFromMatchingTypes(sources: Type[], targets: Type[], matches: (s: Type, t: Type) => boolean): [Type[], Type[]] {
1576815760 let matchedSources: Type[] | undefined;
1576915761 let matchedTargets: Type[] | undefined;
0 commit comments