Skip to content

Commit f028fa3

Browse files
authored
Merge pull request #9746 from Microsoft/instantiate-this-for-contextually-typed-type-parameters
Instantiate this for contextually typed type parameters
2 parents 36130ff + fc1d6a8 commit f028fa3

9 files changed

+201
-58
lines changed

src/compiler/checker.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3066,9 +3066,14 @@ namespace ts {
30663066
}
30673067
}
30683068
// Use contextual parameter type if one is available
3069-
const type = declaration.symbol.name === "this"
3070-
? getContextuallyTypedThisType(func)
3071-
: getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
3069+
let type: Type;
3070+
if (declaration.symbol.name === "this") {
3071+
const thisParameter = getContextualThisParameter(func);
3072+
type = thisParameter ? getTypeOfSymbol(thisParameter) : undefined;
3073+
}
3074+
else {
3075+
type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
3076+
}
30723077
if (type) {
30733078
return addOptionality(type, /*optional*/ declaration.questionToken && includeOptionality);
30743079
}
@@ -4675,6 +4680,9 @@ namespace ts {
46754680
if (isJSConstructSignature) {
46764681
minArgumentCount--;
46774682
}
4683+
if (!thisParameter && isObjectLiteralMethod(declaration)) {
4684+
thisParameter = getContextualThisParameter(declaration);
4685+
}
46784686

46794687
const classType = declaration.kind === SyntaxKind.Constructor ?
46804688
getDeclaredTypeOfClassOrInterface(getMergedSymbol((<ClassDeclaration>declaration.parent).symbol))
@@ -9110,10 +9118,6 @@ namespace ts {
91109118
return getInferredClassType(classSymbol);
91119119
}
91129120
}
9113-
const type = getContextuallyTypedThisType(container);
9114-
if (type) {
9115-
return type;
9116-
}
91179121

91189122
const thisType = getThisTypeOfDeclaration(container);
91199123
if (thisType) {
@@ -9354,11 +9358,11 @@ namespace ts {
93549358
}
93559359
}
93569360

9357-
function getContextuallyTypedThisType(func: FunctionLikeDeclaration): Type {
9361+
function getContextualThisParameter(func: FunctionLikeDeclaration): Symbol {
93589362
if (isContextSensitiveFunctionOrObjectLiteralMethod(func) && func.kind !== SyntaxKind.ArrowFunction) {
93599363
const contextualSignature = getContextualSignature(func);
93609364
if (contextualSignature) {
9361-
return getThisTypeOfSignature(contextualSignature);
9365+
return contextualSignature.thisParameter;
93629366
}
93639367
}
93649368

@@ -12301,6 +12305,12 @@ namespace ts {
1230112305

1230212306
function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) {
1230312307
const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
12308+
if (context.thisParameter) {
12309+
if (!signature.thisParameter) {
12310+
signature.thisParameter = createTransientSymbol(context.thisParameter, undefined);
12311+
}
12312+
assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper);
12313+
}
1230412314
for (let i = 0; i < len; i++) {
1230512315
const parameter = signature.parameters[i];
1230612316
const contextualParameterType = getTypeAtPosition(context, i);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//// [instantiateContextuallyTypedGenericThis.ts]
2+
interface JQuery {
3+
each<T>(
4+
collection: T[], callback: (this: T, dit: T) => T
5+
): T[];
6+
}
7+
8+
let $: JQuery;
9+
let lines: string[];
10+
$.each(lines, function(dit) {
11+
return dit.charAt(0) + this.charAt(1);
12+
});
13+
14+
15+
//// [instantiateContextuallyTypedGenericThis.js]
16+
var $;
17+
var lines;
18+
$.each(lines, function (dit) {
19+
return dit.charAt(0) + this.charAt(1);
20+
});
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
=== tests/cases/compiler/instantiateContextuallyTypedGenericThis.ts ===
2+
interface JQuery {
3+
>JQuery : Symbol(JQuery, Decl(instantiateContextuallyTypedGenericThis.ts, 0, 0))
4+
5+
each<T>(
6+
>each : Symbol(JQuery.each, Decl(instantiateContextuallyTypedGenericThis.ts, 0, 18))
7+
>T : Symbol(T, Decl(instantiateContextuallyTypedGenericThis.ts, 1, 9))
8+
9+
collection: T[], callback: (this: T, dit: T) => T
10+
>collection : Symbol(collection, Decl(instantiateContextuallyTypedGenericThis.ts, 1, 12))
11+
>T : Symbol(T, Decl(instantiateContextuallyTypedGenericThis.ts, 1, 9))
12+
>callback : Symbol(callback, Decl(instantiateContextuallyTypedGenericThis.ts, 2, 24))
13+
>this : Symbol(this, Decl(instantiateContextuallyTypedGenericThis.ts, 2, 36))
14+
>T : Symbol(T, Decl(instantiateContextuallyTypedGenericThis.ts, 1, 9))
15+
>dit : Symbol(dit, Decl(instantiateContextuallyTypedGenericThis.ts, 2, 44))
16+
>T : Symbol(T, Decl(instantiateContextuallyTypedGenericThis.ts, 1, 9))
17+
>T : Symbol(T, Decl(instantiateContextuallyTypedGenericThis.ts, 1, 9))
18+
19+
): T[];
20+
>T : Symbol(T, Decl(instantiateContextuallyTypedGenericThis.ts, 1, 9))
21+
}
22+
23+
let $: JQuery;
24+
>$ : Symbol($, Decl(instantiateContextuallyTypedGenericThis.ts, 6, 3))
25+
>JQuery : Symbol(JQuery, Decl(instantiateContextuallyTypedGenericThis.ts, 0, 0))
26+
27+
let lines: string[];
28+
>lines : Symbol(lines, Decl(instantiateContextuallyTypedGenericThis.ts, 7, 3))
29+
30+
$.each(lines, function(dit) {
31+
>$.each : Symbol(JQuery.each, Decl(instantiateContextuallyTypedGenericThis.ts, 0, 18))
32+
>$ : Symbol($, Decl(instantiateContextuallyTypedGenericThis.ts, 6, 3))
33+
>each : Symbol(JQuery.each, Decl(instantiateContextuallyTypedGenericThis.ts, 0, 18))
34+
>lines : Symbol(lines, Decl(instantiateContextuallyTypedGenericThis.ts, 7, 3))
35+
>dit : Symbol(dit, Decl(instantiateContextuallyTypedGenericThis.ts, 8, 23))
36+
37+
return dit.charAt(0) + this.charAt(1);
38+
>dit.charAt : Symbol(String.charAt, Decl(lib.d.ts, --, --))
39+
>dit : Symbol(dit, Decl(instantiateContextuallyTypedGenericThis.ts, 8, 23))
40+
>charAt : Symbol(String.charAt, Decl(lib.d.ts, --, --))
41+
>this.charAt : Symbol(String.charAt, Decl(lib.d.ts, --, --))
42+
>this : Symbol(this, Decl(instantiateContextuallyTypedGenericThis.ts, 2, 36))
43+
>charAt : Symbol(String.charAt, Decl(lib.d.ts, --, --))
44+
45+
});
46+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
=== tests/cases/compiler/instantiateContextuallyTypedGenericThis.ts ===
2+
interface JQuery {
3+
>JQuery : JQuery
4+
5+
each<T>(
6+
>each : <T>(collection: T[], callback: (this: T, dit: T) => T) => T[]
7+
>T : T
8+
9+
collection: T[], callback: (this: T, dit: T) => T
10+
>collection : T[]
11+
>T : T
12+
>callback : (this: T, dit: T) => T
13+
>this : T
14+
>T : T
15+
>dit : T
16+
>T : T
17+
>T : T
18+
19+
): T[];
20+
>T : T
21+
}
22+
23+
let $: JQuery;
24+
>$ : JQuery
25+
>JQuery : JQuery
26+
27+
let lines: string[];
28+
>lines : string[]
29+
30+
$.each(lines, function(dit) {
31+
>$.each(lines, function(dit) { return dit.charAt(0) + this.charAt(1);}) : string[]
32+
>$.each : <T>(collection: T[], callback: (this: T, dit: T) => T) => T[]
33+
>$ : JQuery
34+
>each : <T>(collection: T[], callback: (this: T, dit: T) => T) => T[]
35+
>lines : string[]
36+
>function(dit) { return dit.charAt(0) + this.charAt(1);} : (this: string, dit: string) => string
37+
>dit : string
38+
39+
return dit.charAt(0) + this.charAt(1);
40+
>dit.charAt(0) + this.charAt(1) : string
41+
>dit.charAt(0) : string
42+
>dit.charAt : (pos: number) => string
43+
>dit : string
44+
>charAt : (pos: number) => string
45+
>0 : number
46+
>this.charAt(1) : string
47+
>this.charAt : (pos: number) => string
48+
>this : string
49+
>charAt : (pos: number) => string
50+
>1 : number
51+
52+
});
53+

tests/baselines/reference/thisTypeInFunctions.symbols

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ let impl: I = {
135135

136136
return this.a;
137137
>this.a : Symbol(a, Decl(thisTypeInFunctions.ts, 24, 30))
138-
>this : Symbol(, Decl(thisTypeInFunctions.ts, 24, 28))
138+
>this : Symbol(this, Decl(thisTypeInFunctions.ts, 24, 23))
139139
>a : Symbol(a, Decl(thisTypeInFunctions.ts, 24, 30))
140140

141141
},
@@ -144,7 +144,7 @@ let impl: I = {
144144

145145
return this.a;
146146
>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13))
147-
>this : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21))
147+
>this : Symbol(this, Decl(thisTypeInFunctions.ts, 25, 22))
148148
>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13))
149149

150150
},
@@ -153,7 +153,7 @@ let impl: I = {
153153

154154
return this.a;
155155
>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13))
156-
>this : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21))
156+
>this : Symbol(this, Decl(thisTypeInFunctions.ts, 26, 17))
157157
>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13))
158158

159159
},
@@ -173,15 +173,15 @@ impl.explicitStructural = function() { return this.a; };
173173
>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 37, 3))
174174
>explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 23, 38))
175175
>this.a : Symbol(a, Decl(thisTypeInFunctions.ts, 24, 30))
176-
>this : Symbol(, Decl(thisTypeInFunctions.ts, 24, 28))
176+
>this : Symbol(this, Decl(thisTypeInFunctions.ts, 24, 23))
177177
>a : Symbol(a, Decl(thisTypeInFunctions.ts, 24, 30))
178178

179179
impl.explicitInterface = function() { return this.a; };
180180
>impl.explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 24, 50))
181181
>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 37, 3))
182182
>explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 24, 50))
183183
>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13))
184-
>this : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21))
184+
>this : Symbol(this, Decl(thisTypeInFunctions.ts, 25, 22))
185185
>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13))
186186

187187
impl.explicitStructural = () => 12;
@@ -199,7 +199,7 @@ impl.explicitThis = function () { return this.a; };
199199
>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 37, 3))
200200
>explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 25, 39))
201201
>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13))
202-
>this : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21))
202+
>this : Symbol(this, Decl(thisTypeInFunctions.ts, 26, 17))
203203
>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13))
204204

205205
// parameter checking
@@ -536,7 +536,7 @@ c.explicitC = function(m) { return this.n + m };
536536
>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5))
537537
>m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 23))
538538
>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9))
539-
>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1))
539+
>this : Symbol(this, Decl(thisTypeInFunctions.ts, 9, 14))
540540
>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9))
541541
>m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 23))
542542

@@ -546,7 +546,7 @@ c.explicitProperty = function(m) { return this.n + m };
546546
>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5))
547547
>m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 30))
548548
>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28))
549-
>this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26))
549+
>this : Symbol(this, Decl(thisTypeInFunctions.ts, 12, 21))
550550
>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28))
551551
>m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 30))
552552

@@ -556,7 +556,7 @@ c.explicitThis = function(m) { return this.n + m };
556556
>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14))
557557
>m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 26))
558558
>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9))
559-
>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1))
559+
>this : Symbol(this, Decl(thisTypeInFunctions.ts, 6, 17))
560560
>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9))
561561
>m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 26))
562562

0 commit comments

Comments
 (0)