Skip to content

Commit f344ec1

Browse files
committed
Merge pull request microsoft#3822 from Microsoft/typeArgumentInferenceApparentType
Take the apparent type of the source during type argument inference
2 parents 649e40b + 51c7164 commit f344ec1

9 files changed

+158
-23
lines changed

src/compiler/checker.ts

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5538,30 +5538,33 @@ namespace ts {
55385538
inferFromTypes(sourceType, target);
55395539
}
55405540
}
5541-
else if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
5542-
(target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
5543-
// If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
5544-
if (isInProcess(source, target)) {
5545-
return;
5546-
}
5547-
if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) {
5548-
return;
5549-
}
5541+
else {
5542+
source = getApparentType(source);
5543+
if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
5544+
(target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
5545+
// If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
5546+
if (isInProcess(source, target)) {
5547+
return;
5548+
}
5549+
if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) {
5550+
return;
5551+
}
55505552

5551-
if (depth === 0) {
5552-
sourceStack = [];
5553-
targetStack = [];
5554-
}
5555-
sourceStack[depth] = source;
5556-
targetStack[depth] = target;
5557-
depth++;
5558-
inferFromProperties(source, target);
5559-
inferFromSignatures(source, target, SignatureKind.Call);
5560-
inferFromSignatures(source, target, SignatureKind.Construct);
5561-
inferFromIndexTypes(source, target, IndexKind.String, IndexKind.String);
5562-
inferFromIndexTypes(source, target, IndexKind.Number, IndexKind.Number);
5563-
inferFromIndexTypes(source, target, IndexKind.String, IndexKind.Number);
5564-
depth--;
5553+
if (depth === 0) {
5554+
sourceStack = [];
5555+
targetStack = [];
5556+
}
5557+
sourceStack[depth] = source;
5558+
targetStack[depth] = target;
5559+
depth++;
5560+
inferFromProperties(source, target);
5561+
inferFromSignatures(source, target, SignatureKind.Call);
5562+
inferFromSignatures(source, target, SignatureKind.Construct);
5563+
inferFromIndexTypes(source, target, IndexKind.String, IndexKind.String);
5564+
inferFromIndexTypes(source, target, IndexKind.Number, IndexKind.Number);
5565+
inferFromIndexTypes(source, target, IndexKind.String, IndexKind.Number);
5566+
depth--;
5567+
}
55655568
}
55665569
}
55675570

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//// [typeArgumentInferenceApparentType1.ts]
2+
function method<T>(iterable: Iterable<T>): T {
3+
return;
4+
}
5+
6+
var res: string = method("test");
7+
8+
//// [typeArgumentInferenceApparentType1.js]
9+
function method(iterable) {
10+
return;
11+
}
12+
var res = method("test");
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
=== tests/cases/compiler/typeArgumentInferenceApparentType1.ts ===
2+
function method<T>(iterable: Iterable<T>): T {
3+
>method : Symbol(method, Decl(typeArgumentInferenceApparentType1.ts, 0, 0))
4+
>T : Symbol(T, Decl(typeArgumentInferenceApparentType1.ts, 0, 16))
5+
>iterable : Symbol(iterable, Decl(typeArgumentInferenceApparentType1.ts, 0, 19))
6+
>Iterable : Symbol(Iterable, Decl(lib.d.ts, 1681, 1))
7+
>T : Symbol(T, Decl(typeArgumentInferenceApparentType1.ts, 0, 16))
8+
>T : Symbol(T, Decl(typeArgumentInferenceApparentType1.ts, 0, 16))
9+
10+
return;
11+
}
12+
13+
var res: string = method("test");
14+
>res : Symbol(res, Decl(typeArgumentInferenceApparentType1.ts, 4, 3))
15+
>method : Symbol(method, Decl(typeArgumentInferenceApparentType1.ts, 0, 0))
16+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
=== tests/cases/compiler/typeArgumentInferenceApparentType1.ts ===
2+
function method<T>(iterable: Iterable<T>): T {
3+
>method : <T>(iterable: Iterable<T>) => T
4+
>T : T
5+
>iterable : Iterable<T>
6+
>Iterable : Iterable<T>
7+
>T : T
8+
>T : T
9+
10+
return;
11+
}
12+
13+
var res: string = method("test");
14+
>res : string
15+
>method("test") : string
16+
>method : <T>(iterable: Iterable<T>) => T
17+
>"test" : string
18+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//// [typeArgumentInferenceApparentType2.ts]
2+
function method<T>(iterable: Iterable<T>): T {
3+
function inner<U extends Iterable<T>>() {
4+
var u: U;
5+
var res: T = method(u);
6+
}
7+
return;
8+
}
9+
10+
//// [typeArgumentInferenceApparentType2.js]
11+
function method(iterable) {
12+
function inner() {
13+
var u;
14+
var res = method(u);
15+
}
16+
return;
17+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/compiler/typeArgumentInferenceApparentType2.ts ===
2+
function method<T>(iterable: Iterable<T>): T {
3+
>method : Symbol(method, Decl(typeArgumentInferenceApparentType2.ts, 0, 0))
4+
>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16))
5+
>iterable : Symbol(iterable, Decl(typeArgumentInferenceApparentType2.ts, 0, 19))
6+
>Iterable : Symbol(Iterable, Decl(lib.d.ts, 1681, 1))
7+
>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16))
8+
>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16))
9+
10+
function inner<U extends Iterable<T>>() {
11+
>inner : Symbol(inner, Decl(typeArgumentInferenceApparentType2.ts, 0, 46))
12+
>U : Symbol(U, Decl(typeArgumentInferenceApparentType2.ts, 1, 19))
13+
>Iterable : Symbol(Iterable, Decl(lib.d.ts, 1681, 1))
14+
>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16))
15+
16+
var u: U;
17+
>u : Symbol(u, Decl(typeArgumentInferenceApparentType2.ts, 2, 11))
18+
>U : Symbol(U, Decl(typeArgumentInferenceApparentType2.ts, 1, 19))
19+
20+
var res: T = method(u);
21+
>res : Symbol(res, Decl(typeArgumentInferenceApparentType2.ts, 3, 11))
22+
>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16))
23+
>method : Symbol(method, Decl(typeArgumentInferenceApparentType2.ts, 0, 0))
24+
>u : Symbol(u, Decl(typeArgumentInferenceApparentType2.ts, 2, 11))
25+
}
26+
return;
27+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
=== tests/cases/compiler/typeArgumentInferenceApparentType2.ts ===
2+
function method<T>(iterable: Iterable<T>): T {
3+
>method : <T>(iterable: Iterable<T>) => T
4+
>T : T
5+
>iterable : Iterable<T>
6+
>Iterable : Iterable<T>
7+
>T : T
8+
>T : T
9+
10+
function inner<U extends Iterable<T>>() {
11+
>inner : <U extends Iterable<T>>() => void
12+
>U : U
13+
>Iterable : Iterable<T>
14+
>T : T
15+
16+
var u: U;
17+
>u : U
18+
>U : U
19+
20+
var res: T = method(u);
21+
>res : T
22+
>T : T
23+
>method(u) : T
24+
>method : <T>(iterable: Iterable<T>) => T
25+
>u : U
26+
}
27+
return;
28+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//@target: ES6
2+
function method<T>(iterable: Iterable<T>): T {
3+
return;
4+
}
5+
6+
var res: string = method("test");
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//@target: ES6
2+
function method<T>(iterable: Iterable<T>): T {
3+
function inner<U extends Iterable<T>>() {
4+
var u: U;
5+
var res: T = method(u);
6+
}
7+
return;
8+
}

0 commit comments

Comments
 (0)