mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 11:35:42 -06:00
Get contextual type of this parameter correctly
Now the language service also sees the contextual type. Note that with this change, the type display for contextually typed this parameters goes away because there is no symbol. I'll fix type display next.
This commit is contained in:
parent
5821b87eda
commit
80de700be0
@ -7383,6 +7383,10 @@ namespace ts {
|
||||
captureLexicalThis(node, container);
|
||||
}
|
||||
if (isFunctionLike(container)) {
|
||||
const type = getContextuallyTypedThisType(container);
|
||||
if (type) {
|
||||
return type;
|
||||
}
|
||||
const signature = getSignatureFromDeclaration(container);
|
||||
if (signature.thisType) {
|
||||
return signature.thisType;
|
||||
@ -7633,6 +7637,19 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getContextuallyTypedThisType(func: FunctionLikeDeclaration): Type {
|
||||
if ((isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) &&
|
||||
isContextSensitive(func) &&
|
||||
func.kind !== SyntaxKind.ArrowFunction) {
|
||||
const contextualSignature = getContextualSignature(func);
|
||||
if (contextualSignature) {
|
||||
return contextualSignature.thisType;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Return contextual type of parameter or undefined if no contextual type is available
|
||||
function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
|
||||
const func = parameter.parent;
|
||||
@ -10396,12 +10413,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) {
|
||||
if (context.thisType) {
|
||||
if (signature.declaration.kind !== SyntaxKind.ArrowFunction) {
|
||||
// do not contextually type thisType for ArrowFunction.
|
||||
signature.thisType = context.thisType;
|
||||
}
|
||||
}
|
||||
const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
|
||||
for (let i = 0; i < len; i++) {
|
||||
const parameter = signature.parameters[i];
|
||||
|
||||
@ -143,7 +143,7 @@ function implicitThis(n: number): number {
|
||||
let impl: I = {
|
||||
>impl : I
|
||||
>I : I
|
||||
>{ a: 12, explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) explicitVoid1() { return 12; }, explicitStructural() { return this.a; }, explicitInterface() { return this.a; }, explicitThis() { return this.a; }, implicitMethod() { return this.a; }, implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?)} : { a: number; explicitVoid2: () => any; explicitVoid1(): number; explicitStructural(this: { a: number; }): number; explicitInterface(this: I): number; explicitThis(this: I): number; implicitMethod(this: I): number; implicitFunction: () => any; }
|
||||
>{ a: 12, explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) explicitVoid1() { return 12; }, explicitStructural() { return this.a; }, explicitInterface() { return this.a; }, explicitThis() { return this.a; }, implicitMethod() { return this.a; }, implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?)} : { a: number; explicitVoid2: () => any; explicitVoid1(): number; explicitStructural(): number; explicitInterface(): number; explicitThis(): number; implicitMethod(): number; implicitFunction: () => any; }
|
||||
|
||||
a: 12,
|
||||
>a : number
|
||||
@ -161,7 +161,7 @@ let impl: I = {
|
||||
>12 : number
|
||||
|
||||
explicitStructural() {
|
||||
>explicitStructural : (this: { a: number; }) => number
|
||||
>explicitStructural : () => number
|
||||
|
||||
return this.a;
|
||||
>this.a : number
|
||||
@ -170,7 +170,7 @@ let impl: I = {
|
||||
|
||||
},
|
||||
explicitInterface() {
|
||||
>explicitInterface : (this: I) => number
|
||||
>explicitInterface : () => number
|
||||
|
||||
return this.a;
|
||||
>this.a : number
|
||||
@ -179,7 +179,7 @@ let impl: I = {
|
||||
|
||||
},
|
||||
explicitThis() {
|
||||
>explicitThis : (this: I) => number
|
||||
>explicitThis : () => number
|
||||
|
||||
return this.a;
|
||||
>this.a : number
|
||||
@ -188,7 +188,7 @@ let impl: I = {
|
||||
|
||||
},
|
||||
implicitMethod() {
|
||||
>implicitMethod : (this: I) => number
|
||||
>implicitMethod : () => number
|
||||
|
||||
return this.a;
|
||||
>this.a : number
|
||||
@ -220,21 +220,21 @@ impl.explicitVoid2 = () => 12;
|
||||
>12 : number
|
||||
|
||||
impl.explicitStructural = function() { return this.a; };
|
||||
>impl.explicitStructural = function() { return this.a; } : (this: { a: number; }) => number
|
||||
>impl.explicitStructural = function() { return this.a; } : () => number
|
||||
>impl.explicitStructural : (this: { a: number; }) => number
|
||||
>impl : I
|
||||
>explicitStructural : (this: { a: number; }) => number
|
||||
>function() { return this.a; } : (this: { a: number; }) => number
|
||||
>function() { return this.a; } : () => number
|
||||
>this.a : number
|
||||
>this : { a: number; }
|
||||
>a : number
|
||||
|
||||
impl.explicitInterface = function() { return this.a; };
|
||||
>impl.explicitInterface = function() { return this.a; } : (this: I) => number
|
||||
>impl.explicitInterface = function() { return this.a; } : () => number
|
||||
>impl.explicitInterface : (this: I) => number
|
||||
>impl : I
|
||||
>explicitInterface : (this: I) => number
|
||||
>function() { return this.a; } : (this: I) => number
|
||||
>function() { return this.a; } : () => number
|
||||
>this.a : number
|
||||
>this : I
|
||||
>a : number
|
||||
@ -256,21 +256,21 @@ impl.explicitInterface = () => 12;
|
||||
>12 : number
|
||||
|
||||
impl.explicitThis = function () { return this.a; };
|
||||
>impl.explicitThis = function () { return this.a; } : (this: I) => number
|
||||
>impl.explicitThis = function () { return this.a; } : () => number
|
||||
>impl.explicitThis : (this: I) => number
|
||||
>impl : I
|
||||
>explicitThis : (this: I) => number
|
||||
>function () { return this.a; } : (this: I) => number
|
||||
>function () { return this.a; } : () => number
|
||||
>this.a : number
|
||||
>this : I
|
||||
>a : number
|
||||
|
||||
impl.implicitMethod = function () { return this.a; };
|
||||
>impl.implicitMethod = function () { return this.a; } : (this: I) => number
|
||||
>impl.implicitMethod = function () { return this.a; } : () => number
|
||||
>impl.implicitMethod : (this: I) => number
|
||||
>impl : I
|
||||
>implicitMethod : (this: I) => number
|
||||
>function () { return this.a; } : (this: I) => number
|
||||
>function () { return this.a; } : () => number
|
||||
>this.a : number
|
||||
>this : I
|
||||
>a : number
|
||||
@ -719,11 +719,11 @@ c.explicitThis = function(this: C, m: number) { return this.n + m };
|
||||
|
||||
// this:any compatibility
|
||||
c.explicitC = function(m) { return this.n + m };
|
||||
>c.explicitC = function(m) { return this.n + m } : (this: C, m: number) => number
|
||||
>c.explicitC = function(m) { return this.n + m } : (m: number) => number
|
||||
>c.explicitC : (this: C, m: number) => number
|
||||
>c : C
|
||||
>explicitC : (this: C, m: number) => number
|
||||
>function(m) { return this.n + m } : (this: C, m: number) => number
|
||||
>function(m) { return this.n + m } : (m: number) => number
|
||||
>m : number
|
||||
>this.n + m : number
|
||||
>this.n : number
|
||||
@ -732,11 +732,11 @@ c.explicitC = function(m) { return this.n + m };
|
||||
>m : number
|
||||
|
||||
c.explicitProperty = function(m) { return this.n + m };
|
||||
>c.explicitProperty = function(m) { return this.n + m } : (this: { n: number; }, m: number) => number
|
||||
>c.explicitProperty = function(m) { return this.n + m } : (m: number) => number
|
||||
>c.explicitProperty : (this: { n: number; }, m: number) => number
|
||||
>c : C
|
||||
>explicitProperty : (this: { n: number; }, m: number) => number
|
||||
>function(m) { return this.n + m } : (this: { n: number; }, m: number) => number
|
||||
>function(m) { return this.n + m } : (m: number) => number
|
||||
>m : number
|
||||
>this.n + m : number
|
||||
>this.n : number
|
||||
@ -745,11 +745,11 @@ c.explicitProperty = function(m) { return this.n + m };
|
||||
>m : number
|
||||
|
||||
c.explicitThis = function(m) { return this.n + m };
|
||||
>c.explicitThis = function(m) { return this.n + m } : (this: C, m: number) => number
|
||||
>c.explicitThis = function(m) { return this.n + m } : (m: number) => number
|
||||
>c.explicitThis : (this: C, m: number) => number
|
||||
>c : C
|
||||
>explicitThis : (this: C, m: number) => number
|
||||
>function(m) { return this.n + m } : (this: C, m: number) => number
|
||||
>function(m) { return this.n + m } : (m: number) => number
|
||||
>m : number
|
||||
>this.n + m : number
|
||||
>this.n : number
|
||||
@ -758,11 +758,11 @@ c.explicitThis = function(m) { return this.n + m };
|
||||
>m : number
|
||||
|
||||
c.implicitThis = function(m) { return this.n + m };
|
||||
>c.implicitThis = function(m) { return this.n + m } : (this: C, m: number) => number
|
||||
>c.implicitThis = function(m) { return this.n + m } : (m: number) => number
|
||||
>c.implicitThis : (this: C, m: number) => number
|
||||
>c : C
|
||||
>implicitThis : (this: C, m: number) => number
|
||||
>function(m) { return this.n + m } : (this: C, m: number) => number
|
||||
>function(m) { return this.n + m } : (m: number) => number
|
||||
>m : number
|
||||
>this.n + m : number
|
||||
>this.n : number
|
||||
|
||||
@ -42,6 +42,17 @@
|
||||
////function explicitLiteral(th/*14*/is: { n: number }): void {
|
||||
//// console.log(th/*15*/is);
|
||||
////}
|
||||
////
|
||||
//// interface ContextualInterface {
|
||||
//// m: number;
|
||||
//// method(this: this, n: number);
|
||||
//// }
|
||||
//// let o: ContextualInterface = {
|
||||
//// m: 12,
|
||||
//// method(n) {
|
||||
//// let x = this/*16*/.m;
|
||||
//// }
|
||||
//// }
|
||||
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs('void');
|
||||
@ -73,4 +84,7 @@ goTo.marker('14');
|
||||
|
||||
verify.quickInfoIs('(parameter) this: {\n n: number;\n}');
|
||||
goTo.marker('15');
|
||||
verify.quickInfoIs('this: {\n n: number;\n}');
|
||||
verify.quickInfoIs('this: {\n n: number;\n}');
|
||||
|
||||
goTo.marker('16');
|
||||
verify.quickInfoIs('this: ContextualInterface');
|
||||
Loading…
x
Reference in New Issue
Block a user