Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typed 'this' in object literal methods #14141

Merged
merged 28 commits into from
Mar 6, 2017
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f6a3a3f
Use '__this__' property in contextual type to indicate type of 'this'
ahejlsberg Feb 14, 2017
8cd6c5d
Introduce ThisType<T> marker interface
ahejlsberg Feb 17, 2017
2ca6164
Default contextual 'this' type is containing object literal
ahejlsberg Feb 17, 2017
e512376
Update tests
ahejlsberg Feb 17, 2017
d7e153d
Accept new baselines
ahejlsberg Feb 17, 2017
fe32bb7
Merge branch 'master' into contextualThisType
ahejlsberg Feb 17, 2017
27346b1
Accept new baselines
ahejlsberg Feb 17, 2017
e3a0687
Contextual this in 'obj.xxx = function(...)' or 'obj[xxx] = function(…
ahejlsberg Feb 17, 2017
168d367
Contextually type 'this' in accessors of object literals
ahejlsberg Feb 23, 2017
c2d8a59
Accept new baselines
ahejlsberg Feb 23, 2017
ec292c9
Update test
ahejlsberg Feb 23, 2017
9b6b6cc
Fix linting error
ahejlsberg Feb 23, 2017
9dc2bae
Use contextual type of object literal as 'this' in methods
ahejlsberg Feb 25, 2017
16f4030
Accept new baselines
ahejlsberg Feb 25, 2017
20b4523
Rename applyToContextualType to mapType and remove old mapType
ahejlsberg Feb 25, 2017
6fdd929
Update test
ahejlsberg Feb 25, 2017
cd87d90
Update comment
ahejlsberg Feb 27, 2017
5bda48b
Add tests
ahejlsberg Feb 27, 2017
993397b
Introduce CheckMode enum and getContextualMapper() function
ahejlsberg Feb 28, 2017
ff2cfd2
Update test
ahejlsberg Feb 28, 2017
c87c124
Accept new baselines
ahejlsberg Feb 28, 2017
ee7b93c
Merge branch 'master' into contextualThisType
ahejlsberg Feb 28, 2017
21c4300
Enable new behavior only in --noImplicitThis mode
ahejlsberg Mar 1, 2017
25738a8
Update tests
ahejlsberg Mar 1, 2017
f77cd8e
Accept new baselines
ahejlsberg Mar 1, 2017
9d1b325
Update another test
ahejlsberg Mar 1, 2017
7561cdf
Add ThisType<any> to Object.{create|defineProperty|defineProperties}
ahejlsberg Mar 2, 2017
258bb4f
Accept new baselines
ahejlsberg Mar 2, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
363 changes: 209 additions & 154 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,8 @@
/* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
/* @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding)
/* @internal */ emitNode?: EmitNode; // Associated EmitNode (initialized by transforms)
/* @internal */ contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
/* @internal */ contextualMapper?: TypeMapper; // Mapper for contextual type
}

export interface NodeArray<T extends Node> extends Array<T>, TextRange {
Expand Down Expand Up @@ -957,7 +959,6 @@

export interface Expression extends Node {
_expressionBrand: any;
contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
}

export interface OmittedExpression extends Expression {
Expand Down
5 changes: 5 additions & 0 deletions src/lib/es5.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,11 @@ type Record<K extends string, T> = {
[P in K]: T;
}

/**
* Marker for contextual 'this' type
*/
interface ThisType<T> { }

/**
* Represents a raw buffer of binary data, which is used to store data for the
* different typed arrays. ArrayBuffers cannot be read from or written to directly,
Expand Down
6 changes: 6 additions & 0 deletions tests/baselines/reference/castTest.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,13 @@ var p_cast = <Point> ({

return new Point(this.x + dx, this.y + dy);
>Point : Symbol(Point, Decl(castTest.ts, 11, 37))
>this.x : Symbol(Point.x, Decl(castTest.ts, 14, 1))
>this : Symbol(Point, Decl(castTest.ts, 11, 37))
>x : Symbol(Point.x, Decl(castTest.ts, 14, 1))
>dx : Symbol(dx, Decl(castTest.ts, 25, 18))
>this.y : Symbol(Point.y, Decl(castTest.ts, 15, 14))
>this : Symbol(Point, Decl(castTest.ts, 11, 37))
>y : Symbol(Point.y, Decl(castTest.ts, 15, 14))
>dy : Symbol(dy, Decl(castTest.ts, 25, 21))

},
Expand Down
16 changes: 8 additions & 8 deletions tests/baselines/reference/castTest.types
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,15 @@ var p_cast = <Point> ({
return new Point(this.x + dx, this.y + dy);
>new Point(this.x + dx, this.y + dy) : Point
>Point : typeof Point
>this.x + dx : any
>this.x : any
>this : any
>x : any
>this.x + dx : number
>this.x : number
>this : Point
>x : number
>dx : number
>this.y + dy : any
>this.y : any
>this : any
>y : any
>this.y + dy : number
>this.y : number
>this : Point
>y : number
>dy : number

},
Expand Down
7 changes: 7 additions & 0 deletions tests/baselines/reference/commentsOnObjectLiteral3.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,20 @@ var v = {
>a : Symbol(a, Decl(commentsOnObjectLiteral3.ts, 8, 13), Decl(commentsOnObjectLiteral3.ts, 12, 18))

return this.prop;
>this.prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9))
>this : Symbol(v, Decl(commentsOnObjectLiteral3.ts, 1, 7))
>prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9))

} /*trailing 1*/,
//setter
set a(value) {
>a : Symbol(a, Decl(commentsOnObjectLiteral3.ts, 8, 13), Decl(commentsOnObjectLiteral3.ts, 12, 18))
>value : Symbol(value, Decl(commentsOnObjectLiteral3.ts, 14, 7))

this.prop = value;
>this.prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9))
>this : Symbol(v, Decl(commentsOnObjectLiteral3.ts, 1, 7))
>prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9))
>value : Symbol(value, Decl(commentsOnObjectLiteral3.ts, 14, 7))

} // trailing 2
Expand Down
26 changes: 13 additions & 13 deletions tests/baselines/reference/commentsOnObjectLiteral3.types
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
=== tests/cases/compiler/commentsOnObjectLiteral3.ts ===

var v = {
>v : { prop: number; func: () => void; func1(): void; a: any; }
>{ //property prop: 1 /* multiple trailing comments */ /*trailing comments*/, //property func: function () { }, //PropertyName + CallSignature func1() { }, //getter get a() { return this.prop; } /*trailing 1*/, //setter set a(value) { this.prop = value; } // trailing 2} : { prop: number; func: () => void; func1(): void; a: any; }
>v : { prop: number; func: () => void; func1(): void; a: number; }
>{ //property prop: 1 /* multiple trailing comments */ /*trailing comments*/, //property func: function () { }, //PropertyName + CallSignature func1() { }, //getter get a() { return this.prop; } /*trailing 1*/, //setter set a(value) { this.prop = value; } // trailing 2} : { prop: number; func: () => void; func1(): void; a: number; }

//property
prop: 1 /* multiple trailing comments */ /*trailing comments*/,
Expand All @@ -21,25 +21,25 @@ var v = {

//getter
get a() {
>a : any
>a : number

return this.prop;
>this.prop : any
>this : any
>prop : any
>this.prop : number
>this : { prop: number; func: () => void; func1(): void; a: number; }
>prop : number

} /*trailing 1*/,
//setter
set a(value) {
>a : any
>value : any
>a : number
>value : number

this.prop = value;
>this.prop = value : any
>this.prop : any
>this : any
>prop : any
>value : any
>this.prop = value : number
>this.prop : number
>this : { prop: number; func: () => void; func1(): void; a: number; }
>prop : number
>value : number

} // trailing 2
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ function /*1*/makePoint(x: number) {
set x(a: number) { this.b = a; }
>x : Symbol(x, Decl(declFileObjectLiteralWithAccessors.ts, 3, 14), Decl(declFileObjectLiteralWithAccessors.ts, 4, 30))
>a : Symbol(a, Decl(declFileObjectLiteralWithAccessors.ts, 5, 14))
>this.b : Symbol(b, Decl(declFileObjectLiteralWithAccessors.ts, 2, 12))
>this : Symbol(__object, Decl(declFileObjectLiteralWithAccessors.ts, 2, 10))
>b : Symbol(b, Decl(declFileObjectLiteralWithAccessors.ts, 2, 12))
>a : Symbol(a, Decl(declFileObjectLiteralWithAccessors.ts, 5, 14))

};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ function /*1*/makePoint(x: number) {
>x : number
>a : number
>this.b = a : number
>this.b : any
>this : any
>b : any
>this.b : number
>this : { b: number; x: number; }
>b : number
>a : number

};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ function /*1*/makePoint(x: number) {
set x(a: number) { this.b = a; }
>x : Symbol(x, Decl(declFileObjectLiteralWithOnlySetter.ts, 3, 14))
>a : Symbol(a, Decl(declFileObjectLiteralWithOnlySetter.ts, 4, 14))
>this.b : Symbol(b, Decl(declFileObjectLiteralWithOnlySetter.ts, 2, 12))
>this : Symbol(__object, Decl(declFileObjectLiteralWithOnlySetter.ts, 2, 10))
>b : Symbol(b, Decl(declFileObjectLiteralWithOnlySetter.ts, 2, 12))
>a : Symbol(a, Decl(declFileObjectLiteralWithOnlySetter.ts, 4, 14))

};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ function /*1*/makePoint(x: number) {
>x : number
>a : number
>this.b = a : number
>this.b : any
>this : any
>b : any
>this.b : number
>this : { b: number; x: number; }
>b : number
>a : number

};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic
m(): this is Foo {
~~~~
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
let dis = this as Foo;
let dis = this as {} as Foo;
return dis.a != null && dis.b != null && dis.c != null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface Foo {

export const obj = {
m(): this is Foo {
let dis = this as Foo;
let dis = this as {} as Foo;
return dis.a != null && dis.b != null && dis.c != null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic
m(): this is Foo {
~~~~
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
let dis = this as Foo;
let dis = this as {} as Foo;
return dis.a != null && dis.b != null && dis.c != null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface Foo {

export const obj = {
m(): this is Foo {
let dis = this as Foo;
let dis = this as {} as Foo;
return dis.a != null && dis.b != null && dis.c != null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ var object = {

get 0() {
return this._0;
>this._0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14))
>this : Symbol(object, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 12))
>_0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14))

},
set 0(x: number) {
>x : Symbol(x, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 6, 10))

this._0 = x;
>this._0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14))
>this : Symbol(object, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 12))
>_0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14))
>x : Symbol(x, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 6, 10))

},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ var object = {

get 0() {
return this._0;
>this._0 : any
>this : any
>_0 : any
>this._0 : number
>this : { _0: number; 0: number; }
>_0 : number

},
set 0(x: number) {
>x : number

this._0 = x;
>this._0 = x : number
>this._0 : any
>this : any
>_0 : any
>this._0 : number
>this : { _0: number; 0: number; }
>_0 : number
>x : number

},
Expand Down
5 changes: 5 additions & 0 deletions tests/baselines/reference/fatarrowfunctions.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ var messenger = {

setTimeout(() => { this.message.toString(); }, 3000);
>setTimeout : Symbol(setTimeout, Decl(fatarrowfunctions.ts, 34, 1))
>this.message.toString : Symbol(String.toString, Decl(lib.d.ts, --, --))
>this.message : Symbol(message, Decl(fatarrowfunctions.ts, 38, 17))
>this : Symbol(messenger, Decl(fatarrowfunctions.ts, 38, 15))
>message : Symbol(message, Decl(fatarrowfunctions.ts, 38, 17))
>toString : Symbol(String.toString, Decl(lib.d.ts, --, --))
}
};

12 changes: 6 additions & 6 deletions tests/baselines/reference/fatarrowfunctions.types
Original file line number Diff line number Diff line change
Expand Up @@ -234,12 +234,12 @@ var messenger = {
>setTimeout(() => { this.message.toString(); }, 3000) : number
>setTimeout : (expression: any, msec?: number, language?: any) => number
>() => { this.message.toString(); } : () => void
>this.message.toString() : any
>this.message.toString : any
>this.message : any
>this : any
>message : any
>toString : any
>this.message.toString() : string
>this.message.toString : () => string
>this.message : string
>this : { message: string; start: () => void; }
>message : string
>toString : () => string
>3000 : 3000
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ var messenger = {

var _self = this;
>_self : Symbol(_self, Decl(fatarrowfunctionsInFunctions.ts, 5, 11))
>this : Symbol(messenger, Decl(fatarrowfunctionsInFunctions.ts, 2, 15))

setTimeout(function() {
>setTimeout : Symbol(setTimeout, Decl(fatarrowfunctionsInFunctions.ts, 0, 0))

_self.message.toString();
>_self.message.toString : Symbol(String.toString, Decl(lib.d.ts, --, --))
>_self.message : Symbol(message, Decl(fatarrowfunctionsInFunctions.ts, 2, 17))
>_self : Symbol(_self, Decl(fatarrowfunctionsInFunctions.ts, 5, 11))
>message : Symbol(message, Decl(fatarrowfunctionsInFunctions.ts, 2, 17))
>toString : Symbol(String.toString, Decl(lib.d.ts, --, --))

}, 3000);
}
Expand Down
16 changes: 8 additions & 8 deletions tests/baselines/reference/fatarrowfunctionsInFunctions.types
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,21 @@ var messenger = {
>function() { var _self = this; setTimeout(function() { _self.message.toString(); }, 3000); } : () => void

var _self = this;
>_self : any
>this : any
>_self : { message: string; start: () => void; }
>this : { message: string; start: () => void; }

setTimeout(function() {
>setTimeout(function() { _self.message.toString(); }, 3000) : number
>setTimeout : (expression: any, msec?: number, language?: any) => number
>function() { _self.message.toString(); } : () => void

_self.message.toString();
>_self.message.toString() : any
>_self.message.toString : any
>_self.message : any
>_self : any
>message : any
>toString : any
>_self.message.toString() : string
>_self.message.toString : () => string
>_self.message : string
>_self : { message: string; start: () => void; }
>message : string
>toString : () => string

}, 3000);
>3000 : 3000
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(21,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(this: void, m: number) => number'.
The 'this' types of each signature are incompatible.
Type 'void' is not assignable to type 'C'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(25,27): error TS2339: Property 'length' does not exist on type 'number'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(33,28): error TS2339: Property 'length' does not exist on type 'number'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(37,9): error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'I'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error TS2339: Property 'length' does not exist on type 'number'.


==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (4 errors) ====
==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (5 errors) ====
interface I {
n: number;
explicitThis(this: this, m: number): number;
Expand Down Expand Up @@ -36,6 +37,8 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error
n: 101,
explicitThis: function (m: number) {
return m + this.n.length; // error, 'length' does not exist on 'number'
~~~~~~
!!! error TS2339: Property 'length' does not exist on type 'number'.
},
implicitThis(m: number): number { return m; }
};
Expand Down
3 changes: 3 additions & 0 deletions tests/baselines/reference/objectSpread.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } }
>plus : Symbol(plus, Decl(objectSpread.ts, 49, 23))
>c : Symbol(c, Decl(objectSpread.ts, 45, 3))
>plus : Symbol(plus, Decl(objectSpread.ts, 49, 48))
>this.p : Symbol(p, Decl(objectSpread.ts, 49, 12))
>this : Symbol(cplus, Decl(objectSpread.ts, 49, 10))
>p : Symbol(p, Decl(objectSpread.ts, 49, 12))

cplus.plus();
>cplus.plus : Symbol(plus, Decl(objectSpread.ts, 49, 23))
Expand Down
12 changes: 6 additions & 6 deletions tests/baselines/reference/objectSpread.types
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,13 @@ let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } }
>cplus : { p: number; plus(): void; }
>p : number
>plus : () => void
>{ ...c, plus() { return this.p + 1; } } : { plus(): any; p: number; }
>{ ...c, plus() { return this.p + 1; } } : { plus(): number; p: number; }
>c : C
>plus : () => any
>this.p + 1 : any
>this.p : any
>this : any
>p : any
>plus : () => number
>this.p + 1 : number
>this.p : number
>this : { p: number; plus(): void; }
>p : number
>1 : 1

cplus.plus();
Expand Down
Loading