From 04e7d811054f712276264f87a7574ba2796cd4bd Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:49:52 -0800 Subject: [PATCH] Add tests and baselines for this-function types. --- .../looseThisTypeInFunctions.errors.txt | 48 + .../reference/looseThisTypeInFunctions.js | 68 ++ .../reference/thisTypeInFunctions.js | 407 +++++++ .../reference/thisTypeInFunctions.symbols | 862 ++++++++++++++ .../reference/thisTypeInFunctions.types | 1037 +++++++++++++++++ .../thisTypeInFunctionsNegative.errors.txt | 509 ++++++++ .../reference/thisTypeInFunctionsNegative.js | 386 ++++++ .../thisType/looseThisTypeInFunctions.ts | 34 + .../types/thisType/thisTypeInFunctions.ts | 209 ++++ .../thisType/thisTypeInFunctionsNegative.ts | 193 +++ .../fourslash/memberListOnExplicitThis.ts | 30 + 11 files changed, 3783 insertions(+) create mode 100644 tests/baselines/reference/looseThisTypeInFunctions.errors.txt create mode 100644 tests/baselines/reference/looseThisTypeInFunctions.js create mode 100644 tests/baselines/reference/thisTypeInFunctions.js create mode 100644 tests/baselines/reference/thisTypeInFunctions.symbols create mode 100644 tests/baselines/reference/thisTypeInFunctions.types create mode 100644 tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt create mode 100644 tests/baselines/reference/thisTypeInFunctionsNegative.js create mode 100644 tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts create mode 100644 tests/cases/conformance/types/thisType/thisTypeInFunctions.ts create mode 100644 tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts create mode 100644 tests/cases/fourslash/memberListOnExplicitThis.ts diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt new file mode 100644 index 00000000000..058a1555ed6 --- /dev/null +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -0,0 +1,48 @@ +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(20,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'void' is not assignable to type 'C'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(27,9): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. + + +==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (2 errors) ==== + interface I { + explicitThis(this: this, m: number): number; + } + interface Unused { + implicitNoThis(m: number): number; + } + class C implements I { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } + } + let c = new C(); + c.explicitVoid = c.explicitThis; // error, 'void' is missing everything + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'C'. + let o = { + explicitThis: function (m) { return m }, + implicitThis(m: number): number { return m } + }; + let i: I = o; + let x = i.explicitThis; + let n = x(12); // callee:void doesn't match this:I + ~~~~~ +!!! error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. + let u: Unused; + let y = u.implicitNoThis; + n = y(12); // ok, callee:void matches this:any + c.explicitVoid = c.implicitThis // ok, implicitThis(this:any) + o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) + o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) + o.implicitThis = i.explicitThis; + \ No newline at end of file diff --git a/tests/baselines/reference/looseThisTypeInFunctions.js b/tests/baselines/reference/looseThisTypeInFunctions.js new file mode 100644 index 00000000000..66677293c5b --- /dev/null +++ b/tests/baselines/reference/looseThisTypeInFunctions.js @@ -0,0 +1,68 @@ +//// [looseThisTypeInFunctions.ts] +interface I { + explicitThis(this: this, m: number): number; +} +interface Unused { + implicitNoThis(m: number): number; +} +class C implements I { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } +} +let c = new C(); +c.explicitVoid = c.explicitThis; // error, 'void' is missing everything +let o = { + explicitThis: function (m) { return m }, + implicitThis(m: number): number { return m } +}; +let i: I = o; +let x = i.explicitThis; +let n = x(12); // callee:void doesn't match this:I +let u: Unused; +let y = u.implicitNoThis; +n = y(12); // ok, callee:void matches this:any +c.explicitVoid = c.implicitThis // ok, implicitThis(this:any) +o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) +o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) +o.implicitThis = i.explicitThis; + + +//// [looseThisTypeInFunctions.js] +var C = (function () { + function C() { + } + C.prototype.explicitThis = function (m) { + return this.n + m; + }; + C.prototype.implicitThis = function (m) { + return this.n + m; + }; + C.prototype.explicitVoid = function (m) { + return m + 1; + }; + return C; +}()); +var c = new C(); +c.explicitVoid = c.explicitThis; // error, 'void' is missing everything +var o = { + explicitThis: function (m) { return m; }, + implicitThis: function (m) { return m; } +}; +var i = o; +var x = i.explicitThis; +var n = x(12); // callee:void doesn't match this:I +var u; +var y = u.implicitNoThis; +n = y(12); // ok, callee:void matches this:any +c.explicitVoid = c.implicitThis; // ok, implicitThis(this:any) +o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) +o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) +o.implicitThis = i.explicitThis; diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js new file mode 100644 index 00000000000..0798843fc44 --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -0,0 +1,407 @@ +//// [thisTypeInFunctions.ts] +// body checking +class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } +} +class D extends C { } +class B { + n: number; +} +interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; + implicitMethod(): number; + implicitFunction: () => number; +} +function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; +} +function justThis(this: { y: number }): number { + return this.y; +} +function implicitThis(n: number): number { + return 12; +} +let impl: 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?) +} +impl.explicitVoid1 = function () { return 12; }; +impl.explicitVoid2 = () => 12; +impl.explicitStructural = function() { return this.a; }; +impl.explicitInterface = function() { return this.a; }; +impl.explicitStructural = () => 12; +impl.explicitInterface = () => 12; +impl.explicitThis = function () { return this.a; }; +impl.implicitMethod = function () { return this.a; }; +impl.implicitMethod = () => 12; +impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) +// parameter checking +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; +let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; +ok.f(13); +implicitThis(12); +implicitAnyOk.f(12); + +let c = new C(); +let d = new D(); +let ripped = c.explicitC; +c.explicitC(12); +c.explicitProperty(12); +c.explicitThis(12); +c.implicitThis(12); +d.explicitC(12); +d.explicitProperty(12); +d.explicitThis(12); +d.implicitThis(12); +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, +} = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +reconstructed.explicitProperty(11); +reconstructed.implicitThis(11); + +// assignment checking +let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any +let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; +let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; + +let unspecifiedLambda: (x: number) => number = x => x + 12; +let specifiedLambda: (this: void, x: number) => number = x => x + 12; +let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; +let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; + + +let explicitCFunction: (this: C, m: number) => number; +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +c.explicitC = explicitCFunction; +c.explicitC = function(this: C, m: number) { return this.n + m }; +c.explicitProperty = explicitPropertyFunction; +c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; +c.explicitProperty = reconstructed.explicitProperty; + +// lambdas are assignable to anything +c.explicitC = m => m; +c.explicitThis = m => m; +c.explicitProperty = m => m; + +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = m => m + this.n; +c.explicitThis = m => m + this.n; +c.explicitProperty = m => m + this.n; + +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +c.explicitThis = function(this: C, m: number) { return this.n + m }; + +// this:any compatibility +c.explicitC = function(m: number) { return this.n + m }; +c.explicitProperty = function(m: number) { return this.n + m }; +c.explicitThis = function(m: number) { return this.n + m }; +c.implicitThis = function(m: number) { return this.n + m }; +c.implicitThis = reconstructed.implicitThis; + +c.explicitC = function(this: B, m: number) { return this.n + m }; + +// this:void compatibility +c.explicitVoid = n => n; + +// class-based assignability +class Base1 { + x: number; + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.y; } + static explicitStatic(this: typeof Base1): number { return this.y; } + static y: number; + +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } +} +class Derived2 extends Base2 { + x: number +} +let b1 = new Base1(); +let b2 = new Base2(); +let d1 = new Derived1(); +let d2 = new Derived2(); +d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) + +// bivariance-allowed cases +d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) +d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) +b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) + +////// use this-type for construction with new //// +function InterfaceThis(this: I) { + this.a = 12; +} +function LiteralTypeThis(this: {x: string}) { + this.x = "ok"; +} +function AnyThis(this: any) { + this.x = "ok"; +} +let interfaceThis = new InterfaceThis(); +let literalTypeThis = new LiteralTypeThis(); +let anyThis = new AnyThis(); + +//// type parameter inference //// +declare var f: { + (this: void, x: number): number, + call(this: (...argArray: any[]) => U, ...argArray: any[]): U; +}; +let n: number = f.call(12); + +function missingTypeIsImplicitAny(this, a: number) { return a; } + +//// [thisTypeInFunctions.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var _this = this; +// body checking +var C = (function () { + function C() { + } + C.prototype.explicitThis = function (m) { + return this.n + m; + }; + C.prototype.implicitThis = function (m) { + return this.n + m; + }; + C.prototype.explicitC = function (m) { + return this.n + m; + }; + C.prototype.explicitProperty = function (m) { + return this.n + m; + }; + C.prototype.explicitVoid = function (m) { + return m + 1; + }; + return C; +}()); +var D = (function (_super) { + __extends(D, _super); + function D() { + _super.apply(this, arguments); + } + return D; +}(C)); +var B = (function () { + function B() { + } + return B; +}()); +function explicitStructural(x) { + return x + this.y; +} +function justThis() { + return this.y; +} +function implicitThis(n) { + return 12; +} +var impl = { + a: 12, + explicitVoid2: function () { return _this.a; }, + explicitVoid1: function () { return 12; }, + explicitStructural: function () { + return this.a; + }, + explicitInterface: function () { + return this.a; + }, + explicitThis: function () { + return this.a; + }, + implicitMethod: function () { + return this.a; + }, + implicitFunction: function () { return _this.a; } +}; +impl.explicitVoid1 = function () { return 12; }; +impl.explicitVoid2 = function () { return 12; }; +impl.explicitStructural = function () { return this.a; }; +impl.explicitInterface = function () { return this.a; }; +impl.explicitStructural = function () { return 12; }; +impl.explicitInterface = function () { return 12; }; +impl.explicitThis = function () { return this.a; }; +impl.implicitMethod = function () { return this.a; }; +impl.implicitMethod = function () { return 12; }; +impl.implicitFunction = function () { return _this.a; }; // ok, this: any because it refers to some outer object (window?) +// parameter checking +var ok = { y: 12, f: explicitStructural }; +var implicitAnyOk = { notSpecified: 12, f: implicitThis }; +ok.f(13); +implicitThis(12); +implicitAnyOk.f(12); +var c = new C(); +var d = new D(); +var ripped = c.explicitC; +c.explicitC(12); +c.explicitProperty(12); +c.explicitThis(12); +c.implicitThis(12); +d.explicitC(12); +d.explicitProperty(12); +d.explicitThis(12); +d.implicitThis(12); +var reconstructed = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +reconstructed.explicitProperty(11); +reconstructed.implicitThis(11); +// assignment checking +var unboundToSpecified = function (x) { return x + _this.y; }; // ok, this:any +var specifiedToSpecified = explicitStructural; +var anyToSpecified = function (x) { return x + 12; }; +var unspecifiedLambda = function (x) { return x + 12; }; +var specifiedLambda = function (x) { return x + 12; }; +var unspecifiedLambdaToSpecified = unspecifiedLambda; +var specifiedLambdaToSpecified = specifiedLambda; +var explicitCFunction; +var explicitPropertyFunction; +c.explicitC = explicitCFunction; +c.explicitC = function (m) { return this.n + m; }; +c.explicitProperty = explicitPropertyFunction; +c.explicitProperty = function (m) { return this.n + m; }; +c.explicitProperty = reconstructed.explicitProperty; +// lambdas are assignable to anything +c.explicitC = function (m) { return m; }; +c.explicitThis = function (m) { return m; }; +c.explicitProperty = function (m) { return m; }; +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = function (m) { return m + _this.n; }; +c.explicitThis = function (m) { return m + _this.n; }; +c.explicitProperty = function (m) { return m + _this.n; }; +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +c.explicitThis = function (m) { return this.n + m; }; +// this:any compatibility +c.explicitC = function (m) { return this.n + m; }; +c.explicitProperty = function (m) { return this.n + m; }; +c.explicitThis = function (m) { return this.n + m; }; +c.implicitThis = function (m) { return this.n + m; }; +c.implicitThis = reconstructed.implicitThis; +c.explicitC = function (m) { return this.n + m; }; +// this:void compatibility +c.explicitVoid = function (n) { return n; }; +// class-based assignability +var Base1 = (function () { + function Base1() { + } + Base1.prototype.implicit = function () { return this.x; }; + Base1.prototype.explicit = function () { return this.x; }; + Base1.implicitStatic = function () { return this.y; }; + Base1.explicitStatic = function () { return this.y; }; + return Base1; +}()); +var Derived1 = (function (_super) { + __extends(Derived1, _super); + function Derived1() { + _super.apply(this, arguments); + } + return Derived1; +}(Base1)); +var Base2 = (function () { + function Base2() { + } + Base2.prototype.implicit = function () { return this.y; }; + Base2.prototype.explicit = function () { return this.x; }; + return Base2; +}()); +var Derived2 = (function (_super) { + __extends(Derived2, _super); + function Derived2() { + _super.apply(this, arguments); + } + return Derived2; +}(Base2)); +var b1 = new Base1(); +var b2 = new Base2(); +var d1 = new Derived1(); +var d2 = new Derived2(); +d2.implicit = d1.implicit; // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +d1.implicit = d2.implicit; // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) +// bivariance-allowed cases +d1.implicit = b2.implicit; // ok, 'y' in D: { x, y } (d assignable e) +d2.implicit = d1.explicit; // ok, 'y' in { x, y } (c assignable to f) +b1.implicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) +b1.explicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) +////// use this-type for construction with new //// +function InterfaceThis() { + this.a = 12; +} +function LiteralTypeThis() { + this.x = "ok"; +} +function AnyThis() { + this.x = "ok"; +} +var interfaceThis = new InterfaceThis(); +var literalTypeThis = new LiteralTypeThis(); +var anyThis = new AnyThis(); +var n = f.call(12); +function missingTypeIsImplicitAny(a) { return a; } diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols new file mode 100644 index 00000000000..1d9ebbd0cf4 --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -0,0 +1,862 @@ +=== tests/cases/conformance/types/thisType/thisTypeInFunctions.ts === +// body checking +class C { +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) + + n: number; +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) + + explicitThis(this: this, m: number): number { +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 3, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 3, 28)) + + return this.n + m; +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 3, 28)) + } + implicitThis(m: number): number { +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 17)) + + return this.n + m; +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 17)) + } + explicitC(this: C, m: number): number { +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 9, 14)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) + + return this.n + m; +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) + } + explicitProperty(this: {n: number}, m: number): number { +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 12, 21)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) + + return this.n + m; +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) + } + explicitVoid(this: void, m: number): number { +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 15, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) + + return m + 1; +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) + } +} +class D extends C { } +>D : Symbol(D, Decl(thisTypeInFunctions.ts, 18, 1)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) + +class B { +>B : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) + + n: number; +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 20, 9)) +} +interface I { +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) + + a: number; +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 23, 13)) + + explicitVoid1(this: void): number; +>explicitVoid1 : Symbol(explicitVoid1, Decl(thisTypeInFunctions.ts, 24, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 25, 18)) + + explicitVoid2(this: void): number; +>explicitVoid2 : Symbol(explicitVoid2, Decl(thisTypeInFunctions.ts, 25, 38)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 26, 18)) + + explicitStructural(this: {a: number}): number; +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 27, 23)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) + + explicitInterface(this: I): number; +>explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 28, 22)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) + + explicitThis(this: this): number; +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 29, 17)) + + implicitMethod(): number; +>implicitMethod : Symbol(implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) + + implicitFunction: () => number; +>implicitFunction : Symbol(implicitFunction, Decl(thisTypeInFunctions.ts, 30, 29)) +} +function explicitStructural(this: { y: number }, x: number): number { +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 32, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 33, 28)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 33, 35)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 33, 48)) + + return x + this.y; +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 33, 48)) +>this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 33, 35)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 33, 33)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 33, 35)) +} +function justThis(this: { y: number }): number { +>justThis : Symbol(justThis, Decl(thisTypeInFunctions.ts, 35, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 36, 18)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 36, 25)) + + return this.y; +>this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 36, 25)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 36, 23)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 36, 25)) +} +function implicitThis(n: number): number { +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 38, 1)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 39, 22)) + + return 12; +} +let impl: I = { +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) + + a: 12, +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 42, 15)) + + explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) +>explicitVoid2 : Symbol(explicitVoid2, Decl(thisTypeInFunctions.ts, 43, 10)) + + explicitVoid1() { return 12; }, +>explicitVoid1 : Symbol(explicitVoid1, Decl(thisTypeInFunctions.ts, 44, 32)) + + explicitStructural() { +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 45, 35)) + + return this.a; +>this.a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 27, 28)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) + + }, + explicitInterface() { +>explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 48, 6)) + + return this.a; +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + + }, + explicitThis() { +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 51, 6)) + + return this.a; +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + + }, + implicitMethod() { +>implicitMethod : Symbol(implicitMethod, Decl(thisTypeInFunctions.ts, 54, 6)) + + return this.a; +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + + }, + implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) +>implicitFunction : Symbol(implicitFunction, Decl(thisTypeInFunctions.ts, 57, 6)) +} +impl.explicitVoid1 = function () { return 12; }; +>impl.explicitVoid1 : Symbol(I.explicitVoid1, Decl(thisTypeInFunctions.ts, 24, 14)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitVoid1 : Symbol(I.explicitVoid1, Decl(thisTypeInFunctions.ts, 24, 14)) + +impl.explicitVoid2 = () => 12; +>impl.explicitVoid2 : Symbol(I.explicitVoid2, Decl(thisTypeInFunctions.ts, 25, 38)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitVoid2 : Symbol(I.explicitVoid2, Decl(thisTypeInFunctions.ts, 25, 38)) + +impl.explicitStructural = function() { return this.a; }; +>impl.explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>this.a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 27, 28)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) + +impl.explicitInterface = function() { return this.a; }; +>impl.explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + +impl.explicitStructural = () => 12; +>impl.explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) + +impl.explicitInterface = () => 12; +>impl.explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) + +impl.explicitThis = function () { return this.a; }; +>impl.explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + +impl.implicitMethod = function () { return this.a; }; +>impl.implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + +impl.implicitMethod = () => 12; +>impl.implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) + +impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) +>impl.implicitFunction : Symbol(I.implicitFunction, Decl(thisTypeInFunctions.ts, 30, 29)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>implicitFunction : Symbol(I.implicitFunction, Decl(thisTypeInFunctions.ts, 30, 29)) + +// parameter checking +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; +>ok : Symbol(ok, Decl(thisTypeInFunctions.ts, 71, 3)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 71, 9)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 19)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 71, 24)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 71, 31)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 71, 44)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 71, 70)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 77)) +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 32, 1)) + +let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; +>implicitAnyOk : Symbol(implicitAnyOk, Decl(thisTypeInFunctions.ts, 72, 3)) +>notSpecified : Symbol(notSpecified, Decl(thisTypeInFunctions.ts, 72, 20)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 41)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 72, 46)) +>notSpecified : Symbol(notSpecified, Decl(thisTypeInFunctions.ts, 72, 71)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 89)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 38, 1)) + +ok.f(13); +>ok.f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 19)) +>ok : Symbol(ok, Decl(thisTypeInFunctions.ts, 71, 3)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 19)) + +implicitThis(12); +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 38, 1)) + +implicitAnyOk.f(12); +>implicitAnyOk.f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 41)) +>implicitAnyOk : Symbol(implicitAnyOk, Decl(thisTypeInFunctions.ts, 72, 3)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 41)) + +let c = new C(); +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) + +let d = new D(); +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>D : Symbol(D, Decl(thisTypeInFunctions.ts, 18, 1)) + +let ripped = c.explicitC; +>ripped : Symbol(ripped, Decl(thisTypeInFunctions.ts, 79, 3)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) + +c.explicitC(12); +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) + +c.explicitProperty(12); +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) + +c.explicitThis(12); +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) + +c.implicitThis(12); +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) + +d.explicitC(12); +>d.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) + +d.explicitProperty(12); +>d.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) + +d.explicitThis(12); +>d.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) + +d.implicitThis(12); +>d.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) + +let reconstructed: { +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) + + n: number, +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 88, 20)) + + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 89, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 90, 17)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 90, 25)) + + implicitThis(m: number): number, +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 91, 17)) + + explicitC(this: C, m: number): number, +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 91, 36)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 92, 14)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 92, 22)) + + explicitProperty: (this: {n : number}, m: number) => number, +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 93, 23)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 93, 30)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 93, 42)) + + explicitVoid(this: void, m: number): number, +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 93, 64)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 94, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 94, 28)) + +} = { + n: 12, +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 95, 5)) + + explicitThis: c.explicitThis, +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 96, 10)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) + + implicitThis: c.implicitThis, +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 97, 33)) +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) + + explicitC: c.explicitC, +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 98, 33)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) + + explicitProperty: c.explicitProperty, +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 99, 27)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) + + explicitVoid: c.explicitVoid +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 100, 41)) +>c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) + +}; +reconstructed.explicitProperty(11); +>reconstructed.explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) + +reconstructed.implicitThis(11); +>reconstructed.implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) + +// assignment checking +let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any +>unboundToSpecified : Symbol(unboundToSpecified, Decl(thisTypeInFunctions.ts, 107, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 107, 25)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 107, 32)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 107, 45)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 107, 68)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 107, 68)) + +let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; +>specifiedToSpecified : Symbol(specifiedToSpecified, Decl(thisTypeInFunctions.ts, 108, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 108, 27)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 108, 34)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 108, 45)) +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 32, 1)) + +let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; +>anyToSpecified : Symbol(anyToSpecified, Decl(thisTypeInFunctions.ts, 109, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 109, 21)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 109, 28)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 109, 41)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 109, 74)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 109, 74)) + +let unspecifiedLambda: (x: number) => number = x => x + 12; +>unspecifiedLambda : Symbol(unspecifiedLambda, Decl(thisTypeInFunctions.ts, 111, 3)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 111, 24)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 111, 46)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 111, 46)) + +let specifiedLambda: (this: void, x: number) => number = x => x + 12; +>specifiedLambda : Symbol(specifiedLambda, Decl(thisTypeInFunctions.ts, 112, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 112, 22)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 112, 33)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 112, 56)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 112, 56)) + +let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; +>unspecifiedLambdaToSpecified : Symbol(unspecifiedLambdaToSpecified, Decl(thisTypeInFunctions.ts, 113, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 113, 35)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 113, 42)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 113, 53)) +>unspecifiedLambda : Symbol(unspecifiedLambda, Decl(thisTypeInFunctions.ts, 111, 3)) + +let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; +>specifiedLambdaToSpecified : Symbol(specifiedLambdaToSpecified, Decl(thisTypeInFunctions.ts, 114, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 114, 33)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 114, 40)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 114, 51)) +>specifiedLambda : Symbol(specifiedLambda, Decl(thisTypeInFunctions.ts, 112, 3)) + + +let explicitCFunction: (this: C, m: number) => number; +>explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 117, 24)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 117, 32)) + +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +>explicitPropertyFunction : Symbol(explicitPropertyFunction, Decl(thisTypeInFunctions.ts, 118, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 118, 31)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 118, 38)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 118, 49)) + +c.explicitC = explicitCFunction; +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) + +c.explicitC = function(this: C, m: number) { return this.n + m }; +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 120, 23)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 120, 31)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 120, 31)) + +c.explicitProperty = explicitPropertyFunction; +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitPropertyFunction : Symbol(explicitPropertyFunction, Decl(thisTypeInFunctions.ts, 118, 3)) + +c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 122, 30)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 122, 48)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 122, 35)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 122, 48)) + +c.explicitProperty = reconstructed.explicitProperty; +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>reconstructed.explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) + +// lambdas are assignable to anything +c.explicitC = m => m; +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 13)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 13)) + +c.explicitThis = m => m; +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 16)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 16)) + +c.explicitProperty = m => m; +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 20)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 20)) + +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = m => m + this.n; +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 132, 13)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 132, 13)) + +c.explicitThis = m => m + this.n; +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 133, 16)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 133, 16)) + +c.explicitProperty = m => m + this.n; +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 20)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 20)) + +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) + +c.explicitThis = function(this: C, m: number) { return this.n + m }; +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 138, 26)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) + +// this:any compatibility +c.explicitC = function(m: number) { return this.n + m }; +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23)) + +c.explicitProperty = function(m: number) { return this.n + m }; +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30)) + +c.explicitThis = function(m: number) { return this.n + m }; +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26)) + +c.implicitThis = function(m: number) { return this.n + m }; +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 144, 26)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 144, 26)) + +c.implicitThis = reconstructed.implicitThis; +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>reconstructed.implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) + +c.explicitC = function(this: B, m: number) { return this.n + m }; +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 147, 23)) +>B : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 147, 31)) +>this.n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 20, 9)) +>this : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) +>n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 20, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 147, 31)) + +// this:void compatibility +c.explicitVoid = n => n; +>c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 150, 16)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 150, 16)) + +// class-based assignability +class Base1 { +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) + + x: number; +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) + + public implicit(): number { return this.x; } +>implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) + + explicit(this: Base1): number { return this.x; } +>explicit : Symbol(explicit, Decl(thisTypeInFunctions.ts, 155, 48)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 156, 13)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) + + static implicitStatic(): number { return this.y; } +>implicitStatic : Symbol(Base1.implicitStatic, Decl(thisTypeInFunctions.ts, 156, 52)) +>this.y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) + + static explicitStatic(this: typeof Base1): number { return this.y; } +>explicitStatic : Symbol(Base1.explicitStatic, Decl(thisTypeInFunctions.ts, 157, 54)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 158, 26)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>this.y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) + + static y: number; +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) + +} +class Derived1 extends Base1 { +>Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 161, 1)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) + + y: number +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 162, 30)) +} +class Base2 { +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) + + y: number +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 165, 13)) + + implicit(): number { return this.y; } +>implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 165, 13)) +>this : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 165, 13)) + + explicit(this: Base1): number { return this.x; } +>explicit : Symbol(explicit, Decl(thisTypeInFunctions.ts, 167, 41)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 168, 13)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 153, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 153, 13)) +} +class Derived2 extends Base2 { +>Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 169, 1)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) + + x: number +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 170, 30)) +} +let b1 = new Base1(); +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 173, 3)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) + +let b2 = new Base2(); +>b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 174, 3)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) + +let d1 = new Derived1(); +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 161, 1)) + +let d2 = new Derived2(); +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 169, 1)) + +d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) + +d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) +>d1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) + +// bivariance-allowed cases +d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) +>d1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>b2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 174, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) + +d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) + +b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +>b1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 173, 3)) +>implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) + +b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +>b1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 173, 3)) +>explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) + +////// use this-type for construction with new //// +function InterfaceThis(this: I) { +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 187, 23)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) + + this.a = 12; +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +} +function LiteralTypeThis(this: {x: string}) { +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 190, 25)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) + + this.x = "ok"; +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 190, 30)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +} +function AnyThis(this: any) { +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 193, 17)) + + this.x = "ok"; +} +let interfaceThis = new InterfaceThis(); +>interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 196, 3)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) + +let literalTypeThis = new LiteralTypeThis(); +>literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 197, 3)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) + +let anyThis = new AnyThis(); +>anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 198, 3)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) + +//// type parameter inference //// +declare var f: { +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) + + (this: void, x: number): number, +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 202, 5)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 202, 16)) + + call(this: (...argArray: any[]) => U, ...argArray: any[]): U; +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 203, 12)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 19)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 44)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) + +}; +let n: number = f.call(12); +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 205, 3)) +>f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) + +function missingTypeIsImplicitAny(this, a: number) { return a; } +>missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 205, 27)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 34)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) + diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types new file mode 100644 index 00000000000..36b458b91e0 --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -0,0 +1,1037 @@ +=== tests/cases/conformance/types/thisType/thisTypeInFunctions.ts === +// body checking +class C { +>C : C + + n: number; +>n : number + + explicitThis(this: this, m: number): number { +>explicitThis : (this: this, m: number) => number +>this : this +>m : number + + return this.n + m; +>this.n + m : number +>this.n : number +>this : this +>n : number +>m : number + } + implicitThis(m: number): number { +>implicitThis : (this: this, m: number) => number +>m : number + + return this.n + m; +>this.n + m : number +>this.n : number +>this : this +>n : number +>m : number + } + explicitC(this: C, m: number): number { +>explicitC : (this: C, m: number) => number +>this : C +>C : C +>m : number + + return this.n + m; +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + } + explicitProperty(this: {n: number}, m: number): number { +>explicitProperty : (this: { n: number; }, m: number) => number +>this : { n: number; } +>n : number +>m : number + + return this.n + m; +>this.n + m : number +>this.n : number +>this : { n: number; } +>n : number +>m : number + } + explicitVoid(this: void, m: number): number { +>explicitVoid : (m: number) => number +>this : void +>m : number + + return m + 1; +>m + 1 : number +>m : number +>1 : number + } +} +class D extends C { } +>D : D +>C : C + +class B { +>B : B + + n: number; +>n : number +} +interface I { +>I : I + + a: number; +>a : number + + explicitVoid1(this: void): number; +>explicitVoid1 : () => number +>this : void + + explicitVoid2(this: void): number; +>explicitVoid2 : () => number +>this : void + + explicitStructural(this: {a: number}): number; +>explicitStructural : (this: { a: number; }) => number +>this : { a: number; } +>a : number + + explicitInterface(this: I): number; +>explicitInterface : (this: I) => number +>this : I +>I : I + + explicitThis(this: this): number; +>explicitThis : (this: this) => number +>this : this + + implicitMethod(): number; +>implicitMethod : (this: this) => number + + implicitFunction: () => number; +>implicitFunction : () => number +} +function explicitStructural(this: { y: number }, x: number): number { +>explicitStructural : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number + + return x + this.y; +>x + this.y : number +>x : number +>this.y : number +>this : { y: number; } +>y : number +} +function justThis(this: { y: number }): number { +>justThis : (this: { y: number; }) => number +>this : { y: number; } +>y : number + + return this.y; +>this.y : number +>this : { y: number; } +>y : number +} +function implicitThis(n: number): number { +>implicitThis : (n: number) => number +>n : number + + return 12; +>12 : 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, +>a : number +>12 : number + + explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) +>explicitVoid2 : () => any +>() => this.a : () => any +>this.a : any +>this : any +>a : any + + explicitVoid1() { return 12; }, +>explicitVoid1 : () => number +>12 : number + + explicitStructural() { +>explicitStructural : (this: { a: number; }) => number + + return this.a; +>this.a : number +>this : { a: number; } +>a : number + + }, + explicitInterface() { +>explicitInterface : (this: I) => number + + return this.a; +>this.a : number +>this : I +>a : number + + }, + explicitThis() { +>explicitThis : (this: I) => number + + return this.a; +>this.a : number +>this : I +>a : number + + }, + implicitMethod() { +>implicitMethod : (this: I) => number + + return this.a; +>this.a : number +>this : I +>a : number + + }, + implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) +>implicitFunction : () => any +>() => this.a : () => any +>this.a : any +>this : any +>a : any +} +impl.explicitVoid1 = function () { return 12; }; +>impl.explicitVoid1 = function () { return 12; } : () => number +>impl.explicitVoid1 : () => number +>impl : I +>explicitVoid1 : () => number +>function () { return 12; } : () => number +>12 : number + +impl.explicitVoid2 = () => 12; +>impl.explicitVoid2 = () => 12 : () => number +>impl.explicitVoid2 : () => number +>impl : I +>explicitVoid2 : () => number +>() => 12 : () => number +>12 : number + +impl.explicitStructural = function() { return this.a; }; +>impl.explicitStructural = function() { return this.a; } : (this: { a: number; }) => number +>impl.explicitStructural : (this: { a: number; }) => number +>impl : I +>explicitStructural : (this: { a: number; }) => number +>function() { return this.a; } : (this: { a: number; }) => 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 : (this: I) => number +>impl : I +>explicitInterface : (this: I) => number +>function() { return this.a; } : (this: I) => number +>this.a : number +>this : I +>a : number + +impl.explicitStructural = () => 12; +>impl.explicitStructural = () => 12 : () => number +>impl.explicitStructural : (this: { a: number; }) => number +>impl : I +>explicitStructural : (this: { a: number; }) => number +>() => 12 : () => number +>12 : number + +impl.explicitInterface = () => 12; +>impl.explicitInterface = () => 12 : () => number +>impl.explicitInterface : (this: I) => number +>impl : I +>explicitInterface : (this: I) => number +>() => 12 : () => number +>12 : number + +impl.explicitThis = function () { return this.a; }; +>impl.explicitThis = function () { return this.a; } : (this: I) => number +>impl.explicitThis : (this: I) => number +>impl : I +>explicitThis : (this: I) => number +>function () { return this.a; } : (this: I) => 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 : (this: I) => number +>impl : I +>implicitMethod : (this: I) => number +>function () { return this.a; } : (this: I) => number +>this.a : number +>this : I +>a : number + +impl.implicitMethod = () => 12; +>impl.implicitMethod = () => 12 : () => number +>impl.implicitMethod : (this: I) => number +>impl : I +>implicitMethod : (this: I) => number +>() => 12 : () => number +>12 : number + +impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) +>impl.implicitFunction = () => this.a : () => any +>impl.implicitFunction : () => number +>impl : I +>implicitFunction : () => number +>() => this.a : () => any +>this.a : any +>this : any +>a : any + +// parameter checking +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; +>ok : { y: number; f: (this: { y: number; }, x: number) => number; } +>y : number +>f : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>{ y: 12, f: explicitStructural } : { y: number; f: (this: { y: number; }, x: number) => number; } +>y : number +>12 : number +>f : (this: { y: number; }, x: number) => number +>explicitStructural : (this: { y: number; }, x: number) => number + +let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; +>implicitAnyOk : { notSpecified: number; f: (x: number) => number; } +>notSpecified : number +>f : (x: number) => number +>x : number +>{ notSpecified: 12, f: implicitThis } : { notSpecified: number; f: (n: number) => number; } +>notSpecified : number +>12 : number +>f : (n: number) => number +>implicitThis : (n: number) => number + +ok.f(13); +>ok.f(13) : number +>ok.f : (this: { y: number; }, x: number) => number +>ok : { y: number; f: (this: { y: number; }, x: number) => number; } +>f : (this: { y: number; }, x: number) => number +>13 : number + +implicitThis(12); +>implicitThis(12) : number +>implicitThis : (n: number) => number +>12 : number + +implicitAnyOk.f(12); +>implicitAnyOk.f(12) : number +>implicitAnyOk.f : (x: number) => number +>implicitAnyOk : { notSpecified: number; f: (x: number) => number; } +>f : (x: number) => number +>12 : number + +let c = new C(); +>c : C +>new C() : C +>C : typeof C + +let d = new D(); +>d : D +>new D() : D +>D : typeof D + +let ripped = c.explicitC; +>ripped : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number + +c.explicitC(12); +>c.explicitC(12) : number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>12 : number + +c.explicitProperty(12); +>c.explicitProperty(12) : number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>12 : number + +c.explicitThis(12); +>c.explicitThis(12) : number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>12 : number + +c.implicitThis(12); +>c.implicitThis(12) : number +>c.implicitThis : (this: C, m: number) => number +>c : C +>implicitThis : (this: C, m: number) => number +>12 : number + +d.explicitC(12); +>d.explicitC(12) : number +>d.explicitC : (this: C, m: number) => number +>d : D +>explicitC : (this: C, m: number) => number +>12 : number + +d.explicitProperty(12); +>d.explicitProperty(12) : number +>d.explicitProperty : (this: { n: number; }, m: number) => number +>d : D +>explicitProperty : (this: { n: number; }, m: number) => number +>12 : number + +d.explicitThis(12); +>d.explicitThis(12) : number +>d.explicitThis : (this: D, m: number) => number +>d : D +>explicitThis : (this: D, m: number) => number +>12 : number + +d.implicitThis(12); +>d.implicitThis(12) : number +>d.implicitThis : (this: D, m: number) => number +>d : D +>implicitThis : (this: D, m: number) => number +>12 : number + +let reconstructed: { +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } + + n: number, +>n : number + + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. +>explicitThis : (this: C, m: number) => number +>this : C +>C : C +>m : number + + implicitThis(m: number): number, +>implicitThis : (m: number) => number +>m : number + + explicitC(this: C, m: number): number, +>explicitC : (this: C, m: number) => number +>this : C +>C : C +>m : number + + explicitProperty: (this: {n : number}, m: number) => number, +>explicitProperty : (this: { n: number; }, m: number) => number +>this : { n: number; } +>n : number +>m : number + + explicitVoid(this: void, m: number): number, +>explicitVoid : (m: number) => number +>this : void +>m : number + +} = { +>{ n: 12, explicitThis: c.explicitThis, implicitThis: c.implicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid} : { n: number; explicitThis: (this: C, m: number) => number; implicitThis: (this: C, m: number) => number; explicitC: (this: C, m: number) => number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid: (m: number) => number; } + + n: 12, +>n : number +>12 : number + + explicitThis: c.explicitThis, +>explicitThis : (this: C, m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number + + implicitThis: c.implicitThis, +>implicitThis : (this: C, m: number) => number +>c.implicitThis : (this: C, m: number) => number +>c : C +>implicitThis : (this: C, m: number) => number + + explicitC: c.explicitC, +>explicitC : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number + + explicitProperty: c.explicitProperty, +>explicitProperty : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number + + explicitVoid: c.explicitVoid +>explicitVoid : (m: number) => number +>c.explicitVoid : (m: number) => number +>c : C +>explicitVoid : (m: number) => number + +}; +reconstructed.explicitProperty(11); +>reconstructed.explicitProperty(11) : number +>reconstructed.explicitProperty : (this: { n: number; }, m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>explicitProperty : (this: { n: number; }, m: number) => number +>11 : number + +reconstructed.implicitThis(11); +>reconstructed.implicitThis(11) : number +>reconstructed.implicitThis : (m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>implicitThis : (m: number) => number +>11 : number + +// assignment checking +let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any +>unboundToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>x => x + this.y : (x: number) => any +>x : number +>x + this.y : any +>x : number +>this.y : any +>this : any +>y : any + +let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; +>specifiedToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>explicitStructural : (this: { y: number; }, x: number) => number + +let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; +>anyToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>function(x: number): number { return x + 12; } : (this: { y: number; }, x: number) => number +>x : number +>x + 12 : number +>x : number +>12 : number + +let unspecifiedLambda: (x: number) => number = x => x + 12; +>unspecifiedLambda : (x: number) => number +>x : number +>x => x + 12 : (x: number) => number +>x : number +>x + 12 : number +>x : number +>12 : number + +let specifiedLambda: (this: void, x: number) => number = x => x + 12; +>specifiedLambda : (x: number) => number +>this : void +>x : number +>x => x + 12 : (x: number) => number +>x : number +>x + 12 : number +>x : number +>12 : number + +let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; +>unspecifiedLambdaToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>unspecifiedLambda : (x: number) => number + +let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; +>specifiedLambdaToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>specifiedLambda : (x: number) => number + + +let explicitCFunction: (this: C, m: number) => number; +>explicitCFunction : (this: C, m: number) => number +>this : C +>C : C +>m : number + +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +>explicitPropertyFunction : (this: { n: number; }, m: number) => number +>this : { n: number; } +>n : number +>m : number + +c.explicitC = explicitCFunction; +>c.explicitC = explicitCFunction : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>explicitCFunction : (this: C, m: number) => number + +c.explicitC = function(this: C, m: number) { return this.n + m }; +>c.explicitC = function(this: C, m: number) { return this.n + m } : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>function(this: C, m: number) { return this.n + m } : (this: C, m: number) => number +>this : C +>C : C +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +c.explicitProperty = explicitPropertyFunction; +>c.explicitProperty = explicitPropertyFunction : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>explicitPropertyFunction : (this: { n: number; }, m: number) => number + +c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; +>c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m } : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>function(this: {n: number}, m: number) { return this.n + m } : (this: { n: number; }, m: number) => number +>this : { n: number; } +>n : number +>m : number +>this.n + m : number +>this.n : number +>this : { n: number; } +>n : number +>m : number + +c.explicitProperty = reconstructed.explicitProperty; +>c.explicitProperty = reconstructed.explicitProperty : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>reconstructed.explicitProperty : (this: { n: number; }, m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>explicitProperty : (this: { n: number; }, m: number) => number + +// lambdas are assignable to anything +c.explicitC = m => m; +>c.explicitC = m => m : (m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>m => m : (m: number) => number +>m : number +>m : number + +c.explicitThis = m => m; +>c.explicitThis = m => m : (m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>m => m : (m: number) => number +>m : number +>m : number + +c.explicitProperty = m => m; +>c.explicitProperty = m => m : (m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>m => m : (m: number) => number +>m : number +>m : number + +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = m => m + this.n; +>c.explicitC = m => m + this.n : (m: number) => any +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>m => m + this.n : (m: number) => any +>m : number +>m + this.n : any +>m : number +>this.n : any +>this : any +>n : any + +c.explicitThis = m => m + this.n; +>c.explicitThis = m => m + this.n : (m: number) => any +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>m => m + this.n : (m: number) => any +>m : number +>m + this.n : any +>m : number +>this.n : any +>this : any +>n : any + +c.explicitProperty = m => m + this.n; +>c.explicitProperty = m => m + this.n : (m: number) => any +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>m => m + this.n : (m: number) => any +>m : number +>m + this.n : any +>m : number +>this.n : any +>this : any +>n : any + +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +>c.explicitThis = explicitCFunction : (this: C, m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>explicitCFunction : (this: C, m: number) => number + +c.explicitThis = function(this: C, m: number) { return this.n + m }; +>c.explicitThis = function(this: C, m: number) { return this.n + m } : (this: C, m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>function(this: C, m: number) { return this.n + m } : (this: C, m: number) => number +>this : C +>C : C +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +// this:any compatibility +c.explicitC = function(m: number) { return this.n + m }; +>c.explicitC = function(m: number) { return this.n + m } : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>function(m: number) { return this.n + m } : (this: C, m: number) => number +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +c.explicitProperty = function(m: number) { return this.n + m }; +>c.explicitProperty = function(m: number) { return this.n + m } : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>function(m: number) { return this.n + m } : (this: { n: number; }, m: number) => number +>m : number +>this.n + m : number +>this.n : number +>this : { n: number; } +>n : number +>m : number + +c.explicitThis = function(m: number) { return this.n + m }; +>c.explicitThis = function(m: number) { return this.n + m } : (this: C, m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>function(m: number) { return this.n + m } : (this: C, m: number) => number +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +c.implicitThis = function(m: number) { return this.n + m }; +>c.implicitThis = function(m: number) { return this.n + m } : (this: C, m: number) => number +>c.implicitThis : (this: C, m: number) => number +>c : C +>implicitThis : (this: C, m: number) => number +>function(m: number) { return this.n + m } : (this: C, m: number) => number +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +c.implicitThis = reconstructed.implicitThis; +>c.implicitThis = reconstructed.implicitThis : (m: number) => number +>c.implicitThis : (this: C, m: number) => number +>c : C +>implicitThis : (this: C, m: number) => number +>reconstructed.implicitThis : (m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>implicitThis : (m: number) => number + +c.explicitC = function(this: B, m: number) { return this.n + m }; +>c.explicitC = function(this: B, m: number) { return this.n + m } : (this: B, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>function(this: B, m: number) { return this.n + m } : (this: B, m: number) => number +>this : B +>B : B +>m : number +>this.n + m : number +>this.n : number +>this : B +>n : number +>m : number + +// this:void compatibility +c.explicitVoid = n => n; +>c.explicitVoid = n => n : (n: number) => number +>c.explicitVoid : (m: number) => number +>c : C +>explicitVoid : (m: number) => number +>n => n : (n: number) => number +>n : number +>n : number + +// class-based assignability +class Base1 { +>Base1 : Base1 + + x: number; +>x : number + + public implicit(): number { return this.x; } +>implicit : (this: this) => number +>this.x : number +>this : this +>x : number + + explicit(this: Base1): number { return this.x; } +>explicit : (this: Base1) => number +>this : Base1 +>Base1 : Base1 +>this.x : number +>this : Base1 +>x : number + + static implicitStatic(): number { return this.y; } +>implicitStatic : (this: typeof Base1) => number +>this.y : number +>this : typeof Base1 +>y : number + + static explicitStatic(this: typeof Base1): number { return this.y; } +>explicitStatic : (this: typeof Base1) => number +>this : typeof Base1 +>Base1 : typeof Base1 +>this.y : number +>this : typeof Base1 +>y : number + + static y: number; +>y : number + +} +class Derived1 extends Base1 { +>Derived1 : Derived1 +>Base1 : Base1 + + y: number +>y : number +} +class Base2 { +>Base2 : Base2 + + y: number +>y : number + + implicit(): number { return this.y; } +>implicit : (this: this) => number +>this.y : number +>this : this +>y : number + + explicit(this: Base1): number { return this.x; } +>explicit : (this: Base1) => number +>this : Base1 +>Base1 : Base1 +>this.x : number +>this : Base1 +>x : number +} +class Derived2 extends Base2 { +>Derived2 : Derived2 +>Base2 : Base2 + + x: number +>x : number +} +let b1 = new Base1(); +>b1 : Base1 +>new Base1() : Base1 +>Base1 : typeof Base1 + +let b2 = new Base2(); +>b2 : Base2 +>new Base2() : Base2 +>Base2 : typeof Base2 + +let d1 = new Derived1(); +>d1 : Derived1 +>new Derived1() : Derived1 +>Derived1 : typeof Derived1 + +let d2 = new Derived2(); +>d2 : Derived2 +>new Derived2() : Derived2 +>Derived2 : typeof Derived2 + +d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +>d2.implicit = d1.implicit : (this: Derived1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number +>d1.implicit : (this: Derived1) => number +>d1 : Derived1 +>implicit : (this: Derived1) => number + +d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) +>d1.implicit = d2.implicit : (this: Derived2) => number +>d1.implicit : (this: Derived1) => number +>d1 : Derived1 +>implicit : (this: Derived1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number + +// bivariance-allowed cases +d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) +>d1.implicit = b2.implicit : (this: Base2) => number +>d1.implicit : (this: Derived1) => number +>d1 : Derived1 +>implicit : (this: Derived1) => number +>b2.implicit : (this: Base2) => number +>b2 : Base2 +>implicit : (this: Base2) => number + +d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) +>d2.implicit = d1.explicit : (this: Base1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number +>d1.explicit : (this: Base1) => number +>d1 : Derived1 +>explicit : (this: Base1) => number + +b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +>b1.implicit = d2.implicit : (this: Derived2) => number +>b1.implicit : (this: Base1) => number +>b1 : Base1 +>implicit : (this: Base1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number + +b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +>b1.explicit = d2.implicit : (this: Derived2) => number +>b1.explicit : (this: Base1) => number +>b1 : Base1 +>explicit : (this: Base1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number + +////// use this-type for construction with new //// +function InterfaceThis(this: I) { +>InterfaceThis : (this: I) => void +>this : I +>I : I + + this.a = 12; +>this.a = 12 : number +>this.a : number +>this : I +>a : number +>12 : number +} +function LiteralTypeThis(this: {x: string}) { +>LiteralTypeThis : (this: { x: string; }) => void +>this : { x: string; } +>x : string + + this.x = "ok"; +>this.x = "ok" : string +>this.x : string +>this : { x: string; } +>x : string +>"ok" : string +} +function AnyThis(this: any) { +>AnyThis : () => void +>this : any + + this.x = "ok"; +>this.x = "ok" : string +>this.x : any +>this : any +>x : any +>"ok" : string +} +let interfaceThis = new InterfaceThis(); +>interfaceThis : I +>new InterfaceThis() : I +>InterfaceThis : (this: I) => void + +let literalTypeThis = new LiteralTypeThis(); +>literalTypeThis : { x: string; } +>new LiteralTypeThis() : { x: string; } +>LiteralTypeThis : (this: { x: string; }) => void + +let anyThis = new AnyThis(); +>anyThis : any +>new AnyThis() : any +>AnyThis : () => void + +//// type parameter inference //// +declare var f: { +>f : { (x: number): number; call(this: (...argArray: any[]) => U, ...argArray: any[]): U; } + + (this: void, x: number): number, +>this : void +>x : number + + call(this: (...argArray: any[]) => U, ...argArray: any[]): U; +>call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>U : U +>this : (...argArray: any[]) => U +>argArray : any[] +>U : U +>argArray : any[] +>U : U + +}; +let n: number = f.call(12); +>n : number +>f.call(12) : number +>f.call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>f : { (x: number): number; call(this: (...argArray: any[]) => U, ...argArray: any[]): U; } +>call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>12 : number + +function missingTypeIsImplicitAny(this, a: number) { return a; } +>missingTypeIsImplicitAny : (a: number) => number +>this : any +>a : number +>a : number + diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt new file mode 100644 index 00000000000..49a4380977a --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -0,0 +1,509 @@ +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(16,15): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(44,21): error TS2339: Property 'a' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(55,49): error TS2339: Property 'a' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(58,1): error TS2345: Argument of type 'void' is not assignable to parameter of type '{ a: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(60,1): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(62,1): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(67,21): error TS2339: Property 'notFound' does not exist on type '{ y: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(70,21): error TS2339: Property 'notSpecified' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(74,21): error TS2339: Property 'notSpecified' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(76,79): error TS2322: Type '{ y: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: number; f: (this: { y: number; }, x: number) => number; }'. + Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: number; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(77,97): error TS2322: Type '{ y: string; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. + Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(78,110): error TS2322: Type '{ wrongName: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. + Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(80,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(81,6): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(82,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(83,1): error TS2345: Argument of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. + Types of property 'y' are incompatible. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(84,1): error TS2345: Argument of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. + Property 'y' is missing in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(87,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(88,13): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(89,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(90,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(91,16): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(92,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(93,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(94,16): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(95,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(96,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(97,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(98,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(101,5): error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(x: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'void' is not assignable to type '{ y: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(124,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. + Property 'x' is missing in type 'C'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(125,1): error TS2322: Type '(this: { x: number; }, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type '{ n: number; }' is not assignable to type '{ x: number; }'. + Property 'x' is missing in type '{ n: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(127,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(128,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(129,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(130,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(131,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(132,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(133,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type '{ n: number; }' is not assignable to type 'D'. + Property 'x' is missing in type '{ n: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(134,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type '{ n: number; }' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(135,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(136,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'void' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(137,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'void' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(138,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'void' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(146,51): error TS2339: Property 'x' does not exist on type 'typeof Base1'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(147,69): error TS2339: Property 'x' does not exist on type 'typeof Base1'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(167,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'Base1' is not assignable to type 'Base2'. + Property 'y' is missing in type 'Base1'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'Base1' is not assignable to type 'Base2'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'Base1' is not assignable to type 'Base2'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(180,24): error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,30): error TS2332: 'this' cannot be referenced in current location. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,26): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,57): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,20): error TS2370: A rest parameter must be of an array type. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,23): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,27): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,54): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,23): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,24): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,51): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,28): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,32): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,59): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,32): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,39): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,40): error TS1128: Declaration or statement expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,42): error TS2304: Cannot find name 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,49): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,1): error TS7027: Unreachable code detected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,29): error TS2304: Cannot find name 'm'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,32): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): error TS2304: Cannot find name 'm'. + + +==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (75 errors) ==== + class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return this.n + m; // 'n' doesn't exist on type 'void'. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + } + } + class D { + x: number; + explicitThis(this: this, m: number): number { + return this.x + m; + } + explicitD(this: D, m: number): number { + return this.x + m; + } + implicitD(m: number): number { + return this.x + m; + } + } + interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; // TODO: Allow `this` types for interfaces + implicitMethod(): number; + implicitFunction: () => number; + } + let impl: I = { + a: 12, + explicitVoid1() { + return this.a; // error, no 'a' in 'void' + ~ +!!! error TS2339: Property 'a' does not exist on type 'void'. + }, + explicitVoid2: () => this.a, // ok, `this:any` because it refers to an outer object + explicitStructural: () => 12, + explicitInterface: () => 12, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; // ok, I.a: number + }, + implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' + ~ +!!! error TS2339: Property 'a' does not exist on type 'void'. + } + let implExplicitStructural = impl.explicitStructural; + implExplicitStructural(); // error, no 'a' in 'void' + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'void' is not assignable to parameter of type '{ a: number; }'. + let implExplicitInterface = impl.explicitInterface; + implExplicitInterface(); // error, no 'a' in 'void' + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. + let implImplicitMethod = impl.implicitMethod; + implImplicitMethod(); // error, no 'a' in 'void' + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. + function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; + } + function propertyName(this: { y: number }, x: number): number { + return x + this.notFound; + ~~~~~~~~ +!!! error TS2339: Property 'notFound' does not exist on type '{ y: number; }'. + } + function voidThisSpecified(this: void, x: number): number { + return x + this.notSpecified; + ~~~~~~~~~~~~ +!!! error TS2339: Property 'notSpecified' does not exist on type 'void'. + } + function noThisSpecified(x: number): number { + // this:void unless loose-this is on + return x + this.notSpecified; + ~~~~~~~~~~~~ +!!! error TS2339: Property 'notSpecified' does not exist on type 'void'. + } + let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, explicitStructural }; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ y: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: number; f: (this: { y: number; }, x: number) => number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: number; f: (this: { y: number; }, x: number) => number; }'. + let wrongPropertyType: {y: string, f: (this: { y: number }, x: number) => number} = { y: 'foo', explicitStructural }; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ y: string; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. + let wrongPropertyName: {wrongName: number, f: (this: { y: number }, x: number) => number} = { wrongName: 12, explicitStructural }; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ wrongName: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. + + ok.f(); // not enough arguments + ~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + ok.f('wrong type'); + ~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + ok.f(13, 'too many arguments'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + wrongPropertyType.f(13); + ~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. +!!! error TS2345: Types of property 'y' are incompatible. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + wrongPropertyName.f(13); + ~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. +!!! error TS2345: Property 'y' is missing in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. + + let c = new C(); + c.explicitC(); // not enough arguments + ~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitC('wrong type'); + ~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + c.explicitC(13, 'too many arguments'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitThis(); // not enough arguments + ~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitThis('wrong type 2'); + ~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + c.explicitThis(14, 'too many arguments 2'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.implicitThis(); // not enough arguments + ~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.implicitThis('wrong type 2'); + ~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + c.implicitThis(14, 'too many arguments 2'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitProperty(); // not enough arguments + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitProperty('wrong type 3'); + ~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + c.explicitProperty(15, 'too many arguments 3'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + + // oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. + let specifiedToImplicitVoid: (x: number) => number = explicitStructural; + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(x: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type '{ y: number; }'. + + let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, + } = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, // error not assignable -- c.this:c not assignable to this:void. + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid + };; + + // lambdas have this: void for assignability purposes (and this unbound (free) for body checking) + let d = new D(); + let explicitXProperty: (this: { x: number }, m: number) => number; + + // from differing object types + c.explicitC = function(this: D, m: number) { return this.x + m }; + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. +!!! error TS2322: Property 'x' is missing in type 'C'. + c.explicitProperty = explicitXProperty; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: { x: number; }, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type '{ n: number; }' is not assignable to type '{ x: number; }'. +!!! error TS2322: Property 'x' is missing in type '{ n: number; }'. + + c.explicitC = d.implicitD; + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. + c.explicitC = d.explicitD; + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. + c.explicitC = d.explicitThis; + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. + c.explicitThis = d.implicitD; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. + c.explicitThis = d.explicitD; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. + c.explicitThis = d.explicitThis; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. + c.explicitProperty = d.explicitD; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type '{ n: number; }' is not assignable to type 'D'. +!!! error TS2322: Property 'x' is missing in type '{ n: number; }'. + c.explicitProperty = d.implicitD; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type '{ n: number; }' is not assignable to type 'D'. + c.explicitThis = d.explicitThis; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + c.explicitVoid = d.implicitD; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'D'. + c.explicitVoid = d.explicitD; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'D'. + c.explicitVoid = d.explicitThis; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'D'. + + /// class-based implicit assignability (with inheritance!) /// + + class Base1 { + x: number + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.x; } + ~ +!!! error TS2339: Property 'x' does not exist on type 'typeof Base1'. + static explicitStatic(this: typeof Base1): number { return this.x; } + ~ +!!! error TS2339: Property 'x' does not exist on type 'typeof Base1'. + } + class Derived1 extends Base1 { + y: number + } + class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } + } + class Derived2 extends Base2 { + x: number + } + + + let b1 = new Base1(); + let d1 = new Derived1(); + let b2 = new Base2(); + let d2 = new Derived2(); + + b1.implicit = b2.implicit // error, 'this.y' not in C: { x } (c assignable to e) + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'Base1' is not assignable to type 'Base2'. +!!! error TS2322: Property 'y' is missing in type 'Base1'. + b1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'Base1' is not assignable to type 'Base2'. + + d1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'Base1' is not assignable to type 'Base2'. + + ////// use this-type for construction with new //// + function VoidThis(this: void) { + + } + function ImplicitVoidThis() { + + } + let voidThis = new VoidThis(); + ~~~~~~~~~~~~~~ +!!! error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. + let implicitVoidThis = new ImplicitVoidThis(); + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. + + + ///// parse errors ///// + function notFirst(a: number, this: C): number { return this.n; } + ~~~~~~~ +!!! error TS2332: 'this' cannot be referenced in current location. + function modifiers(async this: C): number { return this.n; } + ~~~~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + function restParam(...this: C): number { return this.n; } + ~~~~~~~ +!!! error TS2370: A rest parameter must be of an array type. + ~~~~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + function optional(this?: C): number { return this.n; } + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS1138: Parameter declaration expected. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + function decorated(@deco() this: C): number { return this.n; } + ~~~~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + function initializer(this: C = new C()): number { return this.n; } + ~ +!!! error TS1005: ',' expected. + ~~~ +!!! error TS1138: Parameter declaration expected. + ~ +!!! error TS1005: ';' expected. + ~ +!!! error TS1128: Declaration or statement expected. + ~~~~~~ +!!! error TS2304: Cannot find name 'number'. + ~ +!!! error TS1005: ';' expected. + + // can't name parameters 'this' in a lambda. + c.explicitProperty = (this, m) => m + this.n; + ~ +!!! error TS7027: Unreachable code detected. + ~ +!!! error TS2304: Cannot find name 'm'. + ~~ +!!! error TS1005: ';' expected. + ~ +!!! error TS2304: Cannot find name 'm'. + \ No newline at end of file diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.js b/tests/baselines/reference/thisTypeInFunctionsNegative.js new file mode 100644 index 00000000000..43d83daef0d --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.js @@ -0,0 +1,386 @@ +//// [thisTypeInFunctionsNegative.ts] +class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return this.n + m; // 'n' doesn't exist on type 'void'. + } +} +class D { + x: number; + explicitThis(this: this, m: number): number { + return this.x + m; + } + explicitD(this: D, m: number): number { + return this.x + m; + } + implicitD(m: number): number { + return this.x + m; + } +} +interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; // TODO: Allow `this` types for interfaces + implicitMethod(): number; + implicitFunction: () => number; +} +let impl: I = { + a: 12, + explicitVoid1() { + return this.a; // error, no 'a' in 'void' + }, + explicitVoid2: () => this.a, // ok, `this:any` because it refers to an outer object + explicitStructural: () => 12, + explicitInterface: () => 12, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; // ok, I.a: number + }, + implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' +} +let implExplicitStructural = impl.explicitStructural; +implExplicitStructural(); // error, no 'a' in 'void' +let implExplicitInterface = impl.explicitInterface; +implExplicitInterface(); // error, no 'a' in 'void' +let implImplicitMethod = impl.implicitMethod; +implImplicitMethod(); // error, no 'a' in 'void' +function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; +} +function propertyName(this: { y: number }, x: number): number { + return x + this.notFound; +} +function voidThisSpecified(this: void, x: number): number { + return x + this.notSpecified; +} +function noThisSpecified(x: number): number { + // this:void unless loose-this is on + return x + this.notSpecified; +} +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, explicitStructural }; +let wrongPropertyType: {y: string, f: (this: { y: number }, x: number) => number} = { y: 'foo', explicitStructural }; +let wrongPropertyName: {wrongName: number, f: (this: { y: number }, x: number) => number} = { wrongName: 12, explicitStructural }; + +ok.f(); // not enough arguments +ok.f('wrong type'); +ok.f(13, 'too many arguments'); +wrongPropertyType.f(13); +wrongPropertyName.f(13); + +let c = new C(); +c.explicitC(); // not enough arguments +c.explicitC('wrong type'); +c.explicitC(13, 'too many arguments'); +c.explicitThis(); // not enough arguments +c.explicitThis('wrong type 2'); +c.explicitThis(14, 'too many arguments 2'); +c.implicitThis(); // not enough arguments +c.implicitThis('wrong type 2'); +c.implicitThis(14, 'too many arguments 2'); +c.explicitProperty(); // not enough arguments +c.explicitProperty('wrong type 3'); +c.explicitProperty(15, 'too many arguments 3'); + +// oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. +let specifiedToImplicitVoid: (x: number) => number = explicitStructural; + +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, +} = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, // error not assignable -- c.this:c not assignable to this:void. + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +};; + +// lambdas have this: void for assignability purposes (and this unbound (free) for body checking) +let d = new D(); +let explicitXProperty: (this: { x: number }, m: number) => number; + +// from differing object types +c.explicitC = function(this: D, m: number) { return this.x + m }; +c.explicitProperty = explicitXProperty; + +c.explicitC = d.implicitD; +c.explicitC = d.explicitD; +c.explicitC = d.explicitThis; +c.explicitThis = d.implicitD; +c.explicitThis = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitProperty = d.explicitD; +c.explicitProperty = d.implicitD; +c.explicitThis = d.explicitThis; +c.explicitVoid = d.implicitD; +c.explicitVoid = d.explicitD; +c.explicitVoid = d.explicitThis; + +/// class-based implicit assignability (with inheritance!) /// + +class Base1 { + x: number + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.x; } + static explicitStatic(this: typeof Base1): number { return this.x; } +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } +} +class Derived2 extends Base2 { + x: number +} + + +let b1 = new Base1(); +let d1 = new Derived1(); +let b2 = new Base2(); +let d2 = new Derived2(); + +b1.implicit = b2.implicit // error, 'this.y' not in C: { x } (c assignable to e) +b1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + +d1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + +////// use this-type for construction with new //// +function VoidThis(this: void) { + +} +function ImplicitVoidThis() { + +} +let voidThis = new VoidThis(); +let implicitVoidThis = new ImplicitVoidThis(); + + +///// parse errors ///// +function notFirst(a: number, this: C): number { return this.n; } +function modifiers(async this: C): number { return this.n; } +function restParam(...this: C): number { return this.n; } +function optional(this?: C): number { return this.n; } +function decorated(@deco() this: C): number { return this.n; } +function initializer(this: C = new C()): number { return this.n; } + +// can't name parameters 'this' in a lambda. +c.explicitProperty = (this, m) => m + this.n; + + +//// [thisTypeInFunctionsNegative.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var _this = this; +var C = (function () { + function C() { + } + C.prototype.explicitThis = function (m) { + return this.n + m; + }; + C.prototype.implicitThis = function (m) { + return this.n + m; + }; + C.prototype.explicitC = function (m) { + return this.n + m; + }; + C.prototype.explicitProperty = function (m) { + return this.n + m; + }; + C.prototype.explicitVoid = function (m) { + return this.n + m; // 'n' doesn't exist on type 'void'. + }; + return C; +}()); +var D = (function () { + function D() { + } + D.prototype.explicitThis = function (m) { + return this.x + m; + }; + D.prototype.explicitD = function (m) { + return this.x + m; + }; + D.prototype.implicitD = function (m) { + return this.x + m; + }; + return D; +}()); +var impl = { + a: 12, + explicitVoid1: function () { + return this.a; // error, no 'a' in 'void' + }, + explicitVoid2: function () { return _this.a; }, + explicitStructural: function () { return 12; }, + explicitInterface: function () { return 12; }, + explicitThis: function () { + return this.a; + }, + implicitMethod: function () { + return this.a; // ok, I.a: number + }, + implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' +}; +var implExplicitStructural = impl.explicitStructural; +implExplicitStructural(); // error, no 'a' in 'void' +var implExplicitInterface = impl.explicitInterface; +implExplicitInterface(); // error, no 'a' in 'void' +var implImplicitMethod = impl.implicitMethod; +implImplicitMethod(); // error, no 'a' in 'void' +function explicitStructural(x) { + return x + this.y; +} +function propertyName(x) { + return x + this.notFound; +} +function voidThisSpecified(x) { + return x + this.notSpecified; +} +function noThisSpecified(x) { + // this:void unless loose-this is on + return x + this.notSpecified; +} +var ok = { y: 12, explicitStructural: explicitStructural }; +var wrongPropertyType = { y: 'foo', explicitStructural: explicitStructural }; +var wrongPropertyName = { wrongName: 12, explicitStructural: explicitStructural }; +ok.f(); // not enough arguments +ok.f('wrong type'); +ok.f(13, 'too many arguments'); +wrongPropertyType.f(13); +wrongPropertyName.f(13); +var c = new C(); +c.explicitC(); // not enough arguments +c.explicitC('wrong type'); +c.explicitC(13, 'too many arguments'); +c.explicitThis(); // not enough arguments +c.explicitThis('wrong type 2'); +c.explicitThis(14, 'too many arguments 2'); +c.implicitThis(); // not enough arguments +c.implicitThis('wrong type 2'); +c.implicitThis(14, 'too many arguments 2'); +c.explicitProperty(); // not enough arguments +c.explicitProperty('wrong type 3'); +c.explicitProperty(15, 'too many arguments 3'); +// oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. +var specifiedToImplicitVoid = explicitStructural; +var reconstructed = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +; +// lambdas have this: void for assignability purposes (and this unbound (free) for body checking) +var d = new D(); +var explicitXProperty; +// from differing object types +c.explicitC = function (m) { return this.x + m; }; +c.explicitProperty = explicitXProperty; +c.explicitC = d.implicitD; +c.explicitC = d.explicitD; +c.explicitC = d.explicitThis; +c.explicitThis = d.implicitD; +c.explicitThis = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitProperty = d.explicitD; +c.explicitProperty = d.implicitD; +c.explicitThis = d.explicitThis; +c.explicitVoid = d.implicitD; +c.explicitVoid = d.explicitD; +c.explicitVoid = d.explicitThis; +/// class-based implicit assignability (with inheritance!) /// +var Base1 = (function () { + function Base1() { + } + Base1.prototype.implicit = function () { return this.x; }; + Base1.prototype.explicit = function () { return this.x; }; + Base1.implicitStatic = function () { return this.x; }; + Base1.explicitStatic = function () { return this.x; }; + return Base1; +}()); +var Derived1 = (function (_super) { + __extends(Derived1, _super); + function Derived1() { + _super.apply(this, arguments); + } + return Derived1; +}(Base1)); +var Base2 = (function () { + function Base2() { + } + Base2.prototype.implicit = function () { return this.y; }; + Base2.prototype.explicit = function () { return this.x; }; + return Base2; +}()); +var Derived2 = (function (_super) { + __extends(Derived2, _super); + function Derived2() { + _super.apply(this, arguments); + } + return Derived2; +}(Base2)); +var b1 = new Base1(); +var d1 = new Derived1(); +var b2 = new Base2(); +var d2 = new Derived2(); +b1.implicit = b2.implicit; // error, 'this.y' not in C: { x } (c assignable to e) +b1.explicit = b2.implicit; // error, 'y' not in C: { x } (c assignable to e) +d1.explicit = b2.implicit; // error, 'y' not in C: { x } (c assignable to e) +////// use this-type for construction with new //// +function VoidThis() { +} +function ImplicitVoidThis() { +} +var voidThis = new VoidThis(); +var implicitVoidThis = new ImplicitVoidThis(); +///// parse errors ///// +function notFirst(a, this) { return this.n; } +function modifiers(, C) { + if ( === void 0) { = this; } + return this.n; +} +function restParam(, C) { return this.n; } +function optional(C) { return this.n; } +function decorated(, C) { + if ( === void 0) { = this; } + return this.n; +} +new C(); +number; +{ + return this.n; +} +// can't name parameters 'this' in a lambda. +c.explicitProperty = (this, m); +m + this.n; diff --git a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts new file mode 100644 index 00000000000..34d1ebd4a8e --- /dev/null +++ b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts @@ -0,0 +1,34 @@ +interface I { + explicitThis(this: this, m: number): number; +} +interface Unused { + implicitNoThis(m: number): number; +} +class C implements I { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } +} +let c = new C(); +c.explicitVoid = c.explicitThis; // error, 'void' is missing everything +let o = { + explicitThis: function (m) { return m }, + implicitThis(m: number): number { return m } +}; +let i: I = o; +let x = i.explicitThis; +let n = x(12); // callee:void doesn't match this:I +let u: Unused; +let y = u.implicitNoThis; +n = y(12); // ok, callee:void matches this:any +c.explicitVoid = c.implicitThis // ok, implicitThis(this:any) +o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) +o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) +o.implicitThis = i.explicitThis; diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts new file mode 100644 index 00000000000..623c880d339 --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -0,0 +1,209 @@ +// @strictThis: true +// body checking +class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } +} +class D extends C { } +class B { + n: number; +} +interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; + implicitMethod(): number; + implicitFunction: () => number; +} +function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; +} +function justThis(this: { y: number }): number { + return this.y; +} +function implicitThis(n: number): number { + return 12; +} +let impl: 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?) +} +impl.explicitVoid1 = function () { return 12; }; +impl.explicitVoid2 = () => 12; +impl.explicitStructural = function() { return this.a; }; +impl.explicitInterface = function() { return this.a; }; +impl.explicitStructural = () => 12; +impl.explicitInterface = () => 12; +impl.explicitThis = function () { return this.a; }; +impl.implicitMethod = function () { return this.a; }; +impl.implicitMethod = () => 12; +impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) +// parameter checking +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; +let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; +ok.f(13); +implicitThis(12); +implicitAnyOk.f(12); + +let c = new C(); +let d = new D(); +let ripped = c.explicitC; +c.explicitC(12); +c.explicitProperty(12); +c.explicitThis(12); +c.implicitThis(12); +d.explicitC(12); +d.explicitProperty(12); +d.explicitThis(12); +d.implicitThis(12); +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, +} = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +reconstructed.explicitProperty(11); +reconstructed.implicitThis(11); + +// assignment checking +let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any +let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; +let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; + +let unspecifiedLambda: (x: number) => number = x => x + 12; +let specifiedLambda: (this: void, x: number) => number = x => x + 12; +let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; +let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; + + +let explicitCFunction: (this: C, m: number) => number; +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +c.explicitC = explicitCFunction; +c.explicitC = function(this: C, m: number) { return this.n + m }; +c.explicitProperty = explicitPropertyFunction; +c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; +c.explicitProperty = reconstructed.explicitProperty; + +// lambdas are assignable to anything +c.explicitC = m => m; +c.explicitThis = m => m; +c.explicitProperty = m => m; + +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = m => m + this.n; +c.explicitThis = m => m + this.n; +c.explicitProperty = m => m + this.n; + +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +c.explicitThis = function(this: C, m: number) { return this.n + m }; + +// this:any compatibility +c.explicitC = function(m: number) { return this.n + m }; +c.explicitProperty = function(m: number) { return this.n + m }; +c.explicitThis = function(m: number) { return this.n + m }; +c.implicitThis = function(m: number) { return this.n + m }; +c.implicitThis = reconstructed.implicitThis; + +c.explicitC = function(this: B, m: number) { return this.n + m }; + +// this:void compatibility +c.explicitVoid = n => n; + +// class-based assignability +class Base1 { + x: number; + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.y; } + static explicitStatic(this: typeof Base1): number { return this.y; } + static y: number; + +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } +} +class Derived2 extends Base2 { + x: number +} +let b1 = new Base1(); +let b2 = new Base2(); +let d1 = new Derived1(); +let d2 = new Derived2(); +d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) + +// bivariance-allowed cases +d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) +d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) +b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) + +////// use this-type for construction with new //// +function InterfaceThis(this: I) { + this.a = 12; +} +function LiteralTypeThis(this: {x: string}) { + this.x = "ok"; +} +function AnyThis(this: any) { + this.x = "ok"; +} +let interfaceThis = new InterfaceThis(); +let literalTypeThis = new LiteralTypeThis(); +let anyThis = new AnyThis(); + +//// type parameter inference //// +declare var f: { + (this: void, x: number): number, + call(this: (...argArray: any[]) => U, ...argArray: any[]): U; +}; +let n: number = f.call(12); + +function missingTypeIsImplicitAny(this, a: number) { return a; } \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts new file mode 100644 index 00000000000..3fba9ad8a73 --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts @@ -0,0 +1,193 @@ +// @strictThis: true +class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return this.n + m; // 'n' doesn't exist on type 'void'. + } +} +class D { + x: number; + explicitThis(this: this, m: number): number { + return this.x + m; + } + explicitD(this: D, m: number): number { + return this.x + m; + } + implicitD(m: number): number { + return this.x + m; + } +} +interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; // TODO: Allow `this` types for interfaces + implicitMethod(): number; + implicitFunction: () => number; +} +let impl: I = { + a: 12, + explicitVoid1() { + return this.a; // error, no 'a' in 'void' + }, + explicitVoid2: () => this.a, // ok, `this:any` because it refers to an outer object + explicitStructural: () => 12, + explicitInterface: () => 12, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; // ok, I.a: number + }, + implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' +} +let implExplicitStructural = impl.explicitStructural; +implExplicitStructural(); // error, no 'a' in 'void' +let implExplicitInterface = impl.explicitInterface; +implExplicitInterface(); // error, no 'a' in 'void' +let implImplicitMethod = impl.implicitMethod; +implImplicitMethod(); // error, no 'a' in 'void' +function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; +} +function propertyName(this: { y: number }, x: number): number { + return x + this.notFound; +} +function voidThisSpecified(this: void, x: number): number { + return x + this.notSpecified; +} +function noThisSpecified(x: number): number { + // this:void unless loose-this is on + return x + this.notSpecified; +} +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, explicitStructural }; +let wrongPropertyType: {y: string, f: (this: { y: number }, x: number) => number} = { y: 'foo', explicitStructural }; +let wrongPropertyName: {wrongName: number, f: (this: { y: number }, x: number) => number} = { wrongName: 12, explicitStructural }; + +ok.f(); // not enough arguments +ok.f('wrong type'); +ok.f(13, 'too many arguments'); +wrongPropertyType.f(13); +wrongPropertyName.f(13); + +let c = new C(); +c.explicitC(); // not enough arguments +c.explicitC('wrong type'); +c.explicitC(13, 'too many arguments'); +c.explicitThis(); // not enough arguments +c.explicitThis('wrong type 2'); +c.explicitThis(14, 'too many arguments 2'); +c.implicitThis(); // not enough arguments +c.implicitThis('wrong type 2'); +c.implicitThis(14, 'too many arguments 2'); +c.explicitProperty(); // not enough arguments +c.explicitProperty('wrong type 3'); +c.explicitProperty(15, 'too many arguments 3'); + +// oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. +let specifiedToImplicitVoid: (x: number) => number = explicitStructural; + +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, +} = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, // error not assignable -- c.this:c not assignable to this:void. + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +};; + +// lambdas have this: void for assignability purposes (and this unbound (free) for body checking) +let d = new D(); +let explicitXProperty: (this: { x: number }, m: number) => number; + +// from differing object types +c.explicitC = function(this: D, m: number) { return this.x + m }; +c.explicitProperty = explicitXProperty; + +c.explicitC = d.implicitD; +c.explicitC = d.explicitD; +c.explicitC = d.explicitThis; +c.explicitThis = d.implicitD; +c.explicitThis = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitProperty = d.explicitD; +c.explicitProperty = d.implicitD; +c.explicitThis = d.explicitThis; +c.explicitVoid = d.implicitD; +c.explicitVoid = d.explicitD; +c.explicitVoid = d.explicitThis; + +/// class-based implicit assignability (with inheritance!) /// + +class Base1 { + x: number + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.x; } + static explicitStatic(this: typeof Base1): number { return this.x; } +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } +} +class Derived2 extends Base2 { + x: number +} + + +let b1 = new Base1(); +let d1 = new Derived1(); +let b2 = new Base2(); +let d2 = new Derived2(); + +b1.implicit = b2.implicit // error, 'this.y' not in C: { x } (c assignable to e) +b1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + +d1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + +////// use this-type for construction with new //// +function VoidThis(this: void) { + +} +function ImplicitVoidThis() { + +} +let voidThis = new VoidThis(); +let implicitVoidThis = new ImplicitVoidThis(); + + +///// parse errors ///// +function notFirst(a: number, this: C): number { return this.n; } +function modifiers(async this: C): number { return this.n; } +function restParam(...this: C): number { return this.n; } +function optional(this?: C): number { return this.n; } +function decorated(@deco() this: C): number { return this.n; } +function initializer(this: C = new C()): number { return this.n; } + +// can't name parameters 'this' in a lambda. +c.explicitProperty = (this, m) => m + this.n; diff --git a/tests/cases/fourslash/memberListOnExplicitThis.ts b/tests/cases/fourslash/memberListOnExplicitThis.ts new file mode 100644 index 00000000000..cf57717183c --- /dev/null +++ b/tests/cases/fourslash/memberListOnExplicitThis.ts @@ -0,0 +1,30 @@ +// @strictThis: true +/// + +////interface Restricted { +//// n: number; +////} +////class C1 implements Restricted { +//// n: number; +//// m: number; +//// f() {this./*1*/} // test on 'this.' +//// g(this: Restricted) {this./*2*/} +////} +////function f() {this./*3*/} +////function g(this: Restricted) {this./*4*/} + +goTo.marker('1'); +verify.memberListContains('f', '(method) C1.f(this: this): void'); +verify.memberListContains('g', '(method) C1.g(this: Restricted): void'); +verify.memberListContains('n', '(property) C1.n: number'); +verify.memberListContains('m', '(property) C1.m: number'); + +goTo.marker('2'); +verify.memberListContains('n', '(property) Restricted.n: number'); + +goTo.marker('3'); +verify.memberListIsEmpty(); + +goTo.marker('4'); +verify.memberListContains('n', '(property) Restricted.n: number'); +