Skip to content

Commit 5b24ea8

Browse files
committed
Restore union-like behavior for inference to conditional types
1 parent 3e68561 commit 5b24ea8

File tree

1 file changed

+32
-28
lines changed

1 file changed

+32
-28
lines changed

src/compiler/checker.ts

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15354,36 +15354,11 @@ namespace ts {
1535415354
inferFromTypes(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target));
1535515355
}
1535615356
else if (target.flags & TypeFlags.Conditional && !contravariant) {
15357-
inferFromTypes(source, getTrueTypeFromConditionalType(<ConditionalType>target));
15358-
inferFromTypes(source, getFalseTypeFromConditionalType(<ConditionalType>target));
15357+
const targetTypes = [getTrueTypeFromConditionalType(<ConditionalType>target), getFalseTypeFromConditionalType(<ConditionalType>target)];
15358+
inferToMultipleTypes(source, targetTypes, /*isIntersection*/ false);
1535915359
}
1536015360
else if (target.flags & TypeFlags.UnionOrIntersection) {
15361-
// We infer from types that are not naked type variables first so that inferences we
15362-
// make from nested naked type variables and given slightly higher priority by virtue
15363-
// of being first in the candidates array.
15364-
let typeVariableCount = 0;
15365-
for (const t of (<UnionOrIntersectionType>target).types) {
15366-
if (getInferenceInfoForType(t)) {
15367-
typeVariableCount++;
15368-
}
15369-
else {
15370-
inferFromTypes(source, t);
15371-
}
15372-
}
15373-
// Inferences directly to naked type variables are given lower priority as they are
15374-
// less specific. For example, when inferring from Promise<string> to T | Promise<T>,
15375-
// we want to infer string for T, not Promise<string> | string. For intersection types
15376-
// we only infer to single naked type variables.
15377-
if (target.flags & TypeFlags.Union ? typeVariableCount !== 0 : typeVariableCount === 1) {
15378-
const savePriority = priority;
15379-
priority |= InferencePriority.NakedTypeVariable;
15380-
for (const t of (<UnionOrIntersectionType>target).types) {
15381-
if (getInferenceInfoForType(t)) {
15382-
inferFromTypes(source, t);
15383-
}
15384-
}
15385-
priority = savePriority;
15386-
}
15361+
inferToMultipleTypes(source, (<UnionOrIntersectionType>target).types, !!(target.flags & TypeFlags.Intersection));
1538715362
}
1538815363
else if (source.flags & TypeFlags.Union) {
1538915364
// Source is a union or intersection type, infer from each constituent type
@@ -15481,6 +15456,35 @@ namespace ts {
1548115456
return undefined;
1548215457
}
1548315458

15459+
function inferToMultipleTypes(source: Type, targets: Type[], isIntersection: boolean) {
15460+
// We infer from types that are not naked type variables first so that inferences we
15461+
// make from nested naked type variables and given slightly higher priority by virtue
15462+
// of being first in the candidates array.
15463+
let typeVariableCount = 0;
15464+
for (const t of targets) {
15465+
if (getInferenceInfoForType(t)) {
15466+
typeVariableCount++;
15467+
}
15468+
else {
15469+
inferFromTypes(source, t);
15470+
}
15471+
}
15472+
// Inferences directly to naked type variables are given lower priority as they are
15473+
// less specific. For example, when inferring from Promise<string> to T | Promise<T>,
15474+
// we want to infer string for T, not Promise<string> | string. For intersection types
15475+
// we only infer to single naked type variables.
15476+
if (isIntersection ? typeVariableCount === 1 : typeVariableCount !== 0) {
15477+
const savePriority = priority;
15478+
priority |= InferencePriority.NakedTypeVariable;
15479+
for (const t of targets) {
15480+
if (getInferenceInfoForType(t)) {
15481+
inferFromTypes(source, t);
15482+
}
15483+
}
15484+
priority = savePriority;
15485+
}
15486+
}
15487+
1548415488
function inferToMappedType(source: Type, target: MappedType, constraintType: Type): boolean {
1548515489
if (constraintType.flags & TypeFlags.Union) {
1548615490
let result = false;

0 commit comments

Comments
 (0)