Skip to content

Commit 89386dd

Browse files
authored
Merge pull request #30801 from Microsoft/tweakUnionTypeInference
Tweak union type inference
2 parents 60346b5 + 40827eb commit 89386dd

File tree

5 files changed

+74
-7
lines changed

5 files changed

+74
-7
lines changed

src/compiler/checker.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14770,17 +14770,25 @@ namespace ts {
1477014770
inferFromTypes(source, (<ConditionalType>target).falseType);
1477114771
}
1477214772
else if (target.flags & TypeFlags.UnionOrIntersection) {
14773+
// We infer from types that are not naked type variables first so that inferences we
14774+
// make from nested naked type variables and given slightly higher priority by virtue
14775+
// of being first in the candidates array.
14776+
for (const t of (<UnionOrIntersectionType>target).types) {
14777+
if (!getInferenceInfoForType(t)) {
14778+
inferFromTypes(source, t);
14779+
}
14780+
}
14781+
// Inferences directly to naked type variables are given lower priority as they are
14782+
// less specific. For example, when inferring from Promise<string> to T | Promise<T>,
14783+
// we want to infer string for T, not Promise<string> | string.
14784+
const savePriority = priority;
14785+
priority |= InferencePriority.NakedTypeVariable;
1477314786
for (const t of (<UnionOrIntersectionType>target).types) {
14774-
const savePriority = priority;
14775-
// Inferences directly to naked type variables are given lower priority as they are
14776-
// less specific. For example, when inferring from Promise<string> to T | Promise<T>,
14777-
// we want to infer string for T, not Promise<string> | string.
1477814787
if (getInferenceInfoForType(t)) {
14779-
priority |= InferencePriority.NakedTypeVariable;
14788+
inferFromTypes(source, t);
1478014789
}
14781-
inferFromTypes(source, t);
14782-
priority = savePriority;
1478314790
}
14791+
priority = savePriority;
1478414792
}
1478514793
else if (source.flags & TypeFlags.Union) {
1478614794
// Source is a union or intersection type, infer from each constituent type
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//// [unionAndIntersectionInference3.ts]
2+
// Repro from #30720
3+
4+
type Maybe<T> = T | undefined;
5+
declare function concatMaybe<T>(...args: (Maybe<T> | Maybe<T>[])[]): T[];
6+
concatMaybe([1, 2, 3], 4);
7+
8+
9+
//// [unionAndIntersectionInference3.js]
10+
"use strict";
11+
// Repro from #30720
12+
concatMaybe([1, 2, 3], 4);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
=== tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference3.ts ===
2+
// Repro from #30720
3+
4+
type Maybe<T> = T | undefined;
5+
>Maybe : Symbol(Maybe, Decl(unionAndIntersectionInference3.ts, 0, 0))
6+
>T : Symbol(T, Decl(unionAndIntersectionInference3.ts, 2, 11))
7+
>T : Symbol(T, Decl(unionAndIntersectionInference3.ts, 2, 11))
8+
9+
declare function concatMaybe<T>(...args: (Maybe<T> | Maybe<T>[])[]): T[];
10+
>concatMaybe : Symbol(concatMaybe, Decl(unionAndIntersectionInference3.ts, 2, 30))
11+
>T : Symbol(T, Decl(unionAndIntersectionInference3.ts, 3, 29))
12+
>args : Symbol(args, Decl(unionAndIntersectionInference3.ts, 3, 32))
13+
>Maybe : Symbol(Maybe, Decl(unionAndIntersectionInference3.ts, 0, 0))
14+
>T : Symbol(T, Decl(unionAndIntersectionInference3.ts, 3, 29))
15+
>Maybe : Symbol(Maybe, Decl(unionAndIntersectionInference3.ts, 0, 0))
16+
>T : Symbol(T, Decl(unionAndIntersectionInference3.ts, 3, 29))
17+
>T : Symbol(T, Decl(unionAndIntersectionInference3.ts, 3, 29))
18+
19+
concatMaybe([1, 2, 3], 4);
20+
>concatMaybe : Symbol(concatMaybe, Decl(unionAndIntersectionInference3.ts, 2, 30))
21+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/conformance/types/typeRelationships/typeInference/unionAndIntersectionInference3.ts ===
2+
// Repro from #30720
3+
4+
type Maybe<T> = T | undefined;
5+
>Maybe : Maybe<T>
6+
7+
declare function concatMaybe<T>(...args: (Maybe<T> | Maybe<T>[])[]): T[];
8+
>concatMaybe : <T>(...args: (T | Maybe<T>[] | undefined)[]) => T[]
9+
>args : (T | Maybe<T>[] | undefined)[]
10+
11+
concatMaybe([1, 2, 3], 4);
12+
>concatMaybe([1, 2, 3], 4) : number[]
13+
>concatMaybe : <T>(...args: (T | Maybe<T>[] | undefined)[]) => T[]
14+
>[1, 2, 3] : number[]
15+
>1 : 1
16+
>2 : 2
17+
>3 : 3
18+
>4 : 4
19+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// @strict: true
2+
3+
// Repro from #30720
4+
5+
type Maybe<T> = T | undefined;
6+
declare function concatMaybe<T>(...args: (Maybe<T> | Maybe<T>[])[]): T[];
7+
concatMaybe([1, 2, 3], 4);

0 commit comments

Comments
 (0)