diff --git a/tests/baselines/reference/thisTypeInObjectLiterals2.js b/tests/baselines/reference/thisTypeInObjectLiterals2.js new file mode 100644 index 00000000000..08f02b6c5af --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.js @@ -0,0 +1,293 @@ +//// [thisTypeInObjectLiterals2.ts] + +// In methods of an object literal with no contextual type, 'this' has the type +// of the object literal. + +let obj1 = { + a: 1, + f() { + return this.a; + }, + b: "hello", + c: { + g() { + this.g(); + } + }, + get d() { + return this.a; + }, + get e() { + return this.b; + }, + set e(value) { + this.b = value; + } +}; + +// In methods of an object literal with a contextual type, 'this' has the +// contextual type. + +type Point = { + x: number; + y: number; + moveBy(dx: number, dy: number): void; +} + +let p1: Point = { + x: 10, + y: 20, + moveBy(dx, dy) { + this.x += dx; + this.y += dy; + } +}; + +declare function f1(p: Point): void; + +f1({ + x: 10, + y: 20, + moveBy(dx, dy) { + this.x += dx; + this.y += dy; + } +}); + +// In methods of an object literal with a contextual type that includes some +// ThisType, 'this' is of type T. + +type ObjectDescriptor = { + data?: D; + methods?: M & ThisType; // Type of 'this' in methods is D & M +} + +declare function makeObject(desc: ObjectDescriptor): D & M; + +let x1 = makeObject({ + data: { x: 0, y: 0 }, + methods: { + moveBy(dx: number, dy: number) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + } + } +}); + +// In methods contained in an object literal with a contextual type that includes +// some ThisType, 'this' is of type T. + +type ObjectDescriptor2 = ThisType & { + data?: D; + methods?: M; +} + +declare function makeObject2(desc: ObjectDescriptor): D & M; + +let x2 = makeObject2({ + data: { x: 0, y: 0 }, + methods: { + moveBy(dx: number, dy: number) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + } + } +}); + +// Proof of concept for typing of Vue.js + +type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; + +type Dictionary = { [x: string]: T } + +type Computed = { + get?(): T; + set?(value: T): void; +} + +type VueOptions = ThisType & { + data?: D | (() => D); + methods?: M; + computed?: Accessors

; +} + +declare const Vue: new (options: VueOptions) => D & M & P; + +let vue = new Vue({ + data: () => ({ x: 1, y: 2 }), + methods: { + f(x: string) { + return this.x; + } + }, + computed: { + test(): number { + return this.x; + }, + hello: { + get() { + return "hi"; + }, + set(value: string) { + } + } + } +}); + +vue; +vue.x; +vue.f("abc"); +vue.test; +vue.hello; + + +//// [thisTypeInObjectLiterals2.js] +// In methods of an object literal with no contextual type, 'this' has the type +// of the object literal. +var obj1 = { + a: 1, + f: function () { + return this.a; + }, + b: "hello", + c: { + g: function () { + this.g(); + } + }, + get d() { + return this.a; + }, + get e() { + return this.b; + }, + set e(value) { + this.b = value; + } +}; +var p1 = { + x: 10, + y: 20, + moveBy: function (dx, dy) { + this.x += dx; + this.y += dy; + } +}; +f1({ + x: 10, + y: 20, + moveBy: function (dx, dy) { + this.x += dx; + this.y += dy; + } +}); +var x1 = makeObject({ + data: { x: 0, y: 0 }, + methods: { + moveBy: function (dx, dy) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + } + } +}); +var x2 = makeObject2({ + data: { x: 0, y: 0 }, + methods: { + moveBy: function (dx, dy) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + } + } +}); +var vue = new Vue({ + data: function () { return ({ x: 1, y: 2 }); }, + methods: { + f: function (x) { + return this.x; + } + }, + computed: { + test: function () { + return this.x; + }, + hello: { + get: function () { + return "hi"; + }, + set: function (value) { + } + } + } +}); +vue; +vue.x; +vue.f("abc"); +vue.test; +vue.hello; + + +//// [thisTypeInObjectLiterals2.d.ts] +declare let obj1: { + a: number; + f(): number; + b: string; + c: { + g(): void; + }; + readonly d: number; + e: string; +}; +declare type Point = { + x: number; + y: number; + moveBy(dx: number, dy: number): void; +}; +declare let p1: Point; +declare function f1(p: Point): void; +declare type ObjectDescriptor = { + data?: D; + methods?: M & ThisType; +}; +declare function makeObject(desc: ObjectDescriptor): D & M; +declare let x1: { + x: number; + y: number; +} & { + moveBy(dx: number, dy: number): void; +}; +declare type ObjectDescriptor2 = ThisType & { + data?: D; + methods?: M; +}; +declare function makeObject2(desc: ObjectDescriptor): D & M; +declare let x2: { + x: number; + y: number; +} & { + moveBy(dx: number, dy: number): void; +}; +declare type Accessors = { + [K in keyof T]: (() => T[K]) | Computed; +}; +declare type Dictionary = { + [x: string]: T; +}; +declare type Computed = { + get?(): T; + set?(value: T): void; +}; +declare type VueOptions = ThisType & { + data?: D | (() => D); + methods?: M; + computed?: Accessors

; +}; +declare const Vue: new (options: VueOptions) => D & M & P; +declare let vue: { + x: number; + y: number; +} & { + f(x: string): number; +} & { + test: number; + hello: string; +}; diff --git a/tests/baselines/reference/thisTypeInObjectLiterals2.symbols b/tests/baselines/reference/thisTypeInObjectLiterals2.symbols new file mode 100644 index 00000000000..ef72c320cce --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.symbols @@ -0,0 +1,410 @@ +=== tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts === + +// In methods of an object literal with no contextual type, 'this' has the type +// of the object literal. + +let obj1 = { +>obj1 : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 3)) + + a: 1, +>a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12)) + + f() { +>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 5, 9)) + + return this.a; +>this.a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12)) +>this : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 10)) +>a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12)) + + }, + b: "hello", +>b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6)) + + c: { +>c : Symbol(c, Decl(thisTypeInObjectLiterals2.ts, 9, 15)) + + g() { +>g : Symbol(g, Decl(thisTypeInObjectLiterals2.ts, 10, 8)) + + this.g(); +>this.g : Symbol(g, Decl(thisTypeInObjectLiterals2.ts, 10, 8)) +>this : Symbol(__object, Decl(thisTypeInObjectLiterals2.ts, 10, 6)) +>g : Symbol(g, Decl(thisTypeInObjectLiterals2.ts, 10, 8)) + } + }, + get d() { +>d : Symbol(d, Decl(thisTypeInObjectLiterals2.ts, 14, 6)) + + return this.a; +>this.a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12)) +>this : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 10)) +>a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12)) + + }, + get e() { +>e : Symbol(e, Decl(thisTypeInObjectLiterals2.ts, 17, 6), Decl(thisTypeInObjectLiterals2.ts, 20, 6)) + + return this.b; +>this.b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6)) +>this : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 10)) +>b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6)) + + }, + set e(value) { +>e : Symbol(e, Decl(thisTypeInObjectLiterals2.ts, 17, 6), Decl(thisTypeInObjectLiterals2.ts, 20, 6)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 21, 10)) + + this.b = value; +>this.b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6)) +>this : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 10)) +>b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 21, 10)) + } +}; + +// In methods of an object literal with a contextual type, 'this' has the +// contextual type. + +type Point = { +>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) + + x: number; +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) + + y: number; +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) + + moveBy(dx: number, dy: number): void; +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 32, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 32, 22)) +} + +let p1: Point = { +>p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 35, 3)) +>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) + + x: 10, +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 35, 17)) + + y: 20, +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 36, 10)) + + moveBy(dx, dy) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 37, 10)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 38, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 38, 14)) + + this.x += dx; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 38, 11)) + + this.y += dy; +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 38, 14)) + } +}; + +declare function f1(p: Point): void; +>f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 42, 2)) +>p : Symbol(p, Decl(thisTypeInObjectLiterals2.ts, 44, 20)) +>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) + +f1({ +>f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 42, 2)) + + x: 10, +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 46, 4)) + + y: 20, +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 47, 10)) + + moveBy(dx, dy) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 48, 10)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 49, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 49, 14)) + + this.x += dx; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 49, 11)) + + this.y += dy; +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 49, 14)) + } +}); + +// In methods of an object literal with a contextual type that includes some +// ThisType, 'this' is of type T. + +type ObjectDescriptor = { +>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 53, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 58, 22)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 58, 24)) + + data?: D; +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 58, 31)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 58, 22)) + + methods?: M & ThisType; // Type of 'this' in methods is D & M +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 59, 13)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 58, 24)) +>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 58, 22)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 58, 24)) +} + +declare function makeObject(desc: ObjectDescriptor): D & M; +>makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 61, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 63, 28)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 63, 30)) +>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 63, 34)) +>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 53, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 63, 28)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 63, 30)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 63, 28)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 63, 30)) + +let x1 = makeObject({ +>x1 : Symbol(x1, Decl(thisTypeInObjectLiterals2.ts, 65, 3)) +>makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 61, 1)) + + data: { x: 0, y: 0 }, +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 65, 21)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 66, 11)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 66, 17)) + + methods: { +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 66, 25)) + + moveBy(dx: number, dy: number) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 67, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 68, 15)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 68, 26)) + + this.x += dx; // Strongly typed this +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 66, 11)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 66, 11)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 68, 15)) + + this.y += dy; // Strongly typed this +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 66, 17)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 66, 17)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 68, 26)) + } + } +}); + +// In methods contained in an object literal with a contextual type that includes +// some ThisType, 'this' is of type T. + +type ObjectDescriptor2 = ThisType & { +>ObjectDescriptor2 : Symbol(ObjectDescriptor2, Decl(thisTypeInObjectLiterals2.ts, 73, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 78, 23)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 78, 25)) +>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 78, 23)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 78, 25)) + + data?: D; +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 78, 50)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 78, 23)) + + methods?: M; +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 79, 13)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 78, 25)) +} + +declare function makeObject2(desc: ObjectDescriptor): D & M; +>makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 81, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 83, 29)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 83, 31)) +>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 83, 35)) +>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 53, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 83, 29)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 83, 31)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 83, 29)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 83, 31)) + +let x2 = makeObject2({ +>x2 : Symbol(x2, Decl(thisTypeInObjectLiterals2.ts, 85, 3)) +>makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 81, 1)) + + data: { x: 0, y: 0 }, +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 85, 22)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 86, 11)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 86, 17)) + + methods: { +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 86, 25)) + + moveBy(dx: number, dy: number) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 87, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 88, 15)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 88, 26)) + + this.x += dx; // Strongly typed this +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 86, 11)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 86, 11)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 88, 15)) + + this.y += dy; // Strongly typed this +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 86, 17)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 86, 17)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 88, 26)) + } + } +}); + +// Proof of concept for typing of Vue.js + +type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; +>Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 93, 3)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 97, 15)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 97, 23)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 97, 15)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 97, 15)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 97, 23)) +>Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 99, 39)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 97, 15)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 97, 23)) + +type Dictionary = { [x: string]: T } +>Dictionary : Symbol(Dictionary, Decl(thisTypeInObjectLiterals2.ts, 97, 70)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 99, 16)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 99, 24)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 99, 16)) + +type Computed = { +>Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 99, 39)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 101, 14)) + + get?(): T; +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 101, 20)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 101, 14)) + + set?(value: T): void; +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 102, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 103, 9)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 101, 14)) +} + +type VueOptions = ThisType & { +>VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 104, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 106, 16)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 106, 18)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 106, 21)) +>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 106, 16)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 106, 18)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 106, 21)) + + data?: D | (() => D); +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 106, 50)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 106, 16)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 106, 16)) + + methods?: M; +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 107, 25)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 106, 18)) + + computed?: Accessors

; +>computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 108, 16)) +>Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 93, 3)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 106, 21)) +} + +declare const Vue: new (options: VueOptions) => D & M & P; +>Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 112, 13)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 112, 24)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 112, 26)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 112, 29)) +>options : Symbol(options, Decl(thisTypeInObjectLiterals2.ts, 112, 33)) +>VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 104, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 112, 24)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 112, 26)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 112, 29)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 112, 24)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 112, 26)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 112, 29)) + +let vue = new Vue({ +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) +>Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 112, 13)) + + data: () => ({ x: 1, y: 2 }), +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 114, 19)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 115, 24)) + + methods: { +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 115, 33)) + + f(x: string) { +>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 116, 14)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 117, 10)) + + return this.x; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) + } + }, + computed: { +>computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 120, 6)) + + test(): number { +>test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 121, 15)) + + return this.x; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) + + }, + hello: { +>hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 124, 10)) + + get() { +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 125, 16)) + + return "hi"; + }, + set(value: string) { +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 128, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 129, 16)) + } + } + } +}); + +vue; +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) + +vue.x; +>vue.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) + +vue.f("abc"); +>vue.f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 116, 14)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) +>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 116, 14)) + +vue.test; +>vue.test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 121, 15)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) +>test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 121, 15)) + +vue.hello; +>vue.hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 124, 10)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) +>hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 124, 10)) + diff --git a/tests/baselines/reference/thisTypeInObjectLiterals2.types b/tests/baselines/reference/thisTypeInObjectLiterals2.types new file mode 100644 index 00000000000..39fd922f617 --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.types @@ -0,0 +1,463 @@ +=== tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts === + +// In methods of an object literal with no contextual type, 'this' has the type +// of the object literal. + +let obj1 = { +>obj1 : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; } +>{ a: 1, f() { return this.a; }, b: "hello", c: { g() { this.g(); } }, get d() { return this.a; }, get e() { return this.b; }, set e(value) { this.b = value; }} : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; } + + a: 1, +>a : number +>1 : 1 + + f() { +>f : () => number + + return this.a; +>this.a : number +>this : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; } +>a : number + + }, + b: "hello", +>b : string +>"hello" : "hello" + + c: { +>c : { g(): void; } +>{ g() { this.g(); } } : { g(): void; } + + g() { +>g : () => void + + this.g(); +>this.g() : void +>this.g : () => void +>this : { g(): void; } +>g : () => void + } + }, + get d() { +>d : number + + return this.a; +>this.a : number +>this : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; } +>a : number + + }, + get e() { +>e : string + + return this.b; +>this.b : string +>this : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; } +>b : string + + }, + set e(value) { +>e : string +>value : string + + this.b = value; +>this.b = value : string +>this.b : string +>this : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; } +>b : string +>value : string + } +}; + +// In methods of an object literal with a contextual type, 'this' has the +// contextual type. + +type Point = { +>Point : Point + + x: number; +>x : number + + y: number; +>y : number + + moveBy(dx: number, dy: number): void; +>moveBy : (dx: number, dy: number) => void +>dx : number +>dy : number +} + +let p1: Point = { +>p1 : Point +>Point : Point +>{ x: 10, y: 20, moveBy(dx, dy) { this.x += dx; this.y += dy; }} : { x: number; y: number; moveBy(dx: number, dy: number): void; } + + x: 10, +>x : number +>10 : 10 + + y: 20, +>y : number +>20 : 20 + + moveBy(dx, dy) { +>moveBy : (dx: number, dy: number) => void +>dx : number +>dy : number + + this.x += dx; +>this.x += dx : number +>this.x : number +>this : Point +>x : number +>dx : number + + this.y += dy; +>this.y += dy : number +>this.y : number +>this : Point +>y : number +>dy : number + } +}; + +declare function f1(p: Point): void; +>f1 : (p: Point) => void +>p : Point +>Point : Point + +f1({ +>f1({ x: 10, y: 20, moveBy(dx, dy) { this.x += dx; this.y += dy; }}) : void +>f1 : (p: Point) => void +>{ x: 10, y: 20, moveBy(dx, dy) { this.x += dx; this.y += dy; }} : { x: number; y: number; moveBy(dx: number, dy: number): void; } + + x: 10, +>x : number +>10 : 10 + + y: 20, +>y : number +>20 : 20 + + moveBy(dx, dy) { +>moveBy : (dx: number, dy: number) => void +>dx : number +>dy : number + + this.x += dx; +>this.x += dx : number +>this.x : number +>this : Point +>x : number +>dx : number + + this.y += dy; +>this.y += dy : number +>this.y : number +>this : Point +>y : number +>dy : number + } +}); + +// In methods of an object literal with a contextual type that includes some +// ThisType, 'this' is of type T. + +type ObjectDescriptor = { +>ObjectDescriptor : ObjectDescriptor +>D : D +>M : M + + data?: D; +>data : D +>D : D + + methods?: M & ThisType; // Type of 'this' in methods is D & M +>methods : M & ThisType +>M : M +>ThisType : ThisType +>D : D +>M : M +} + +declare function makeObject(desc: ObjectDescriptor): D & M; +>makeObject : (desc: ObjectDescriptor) => D & M +>D : D +>M : M +>desc : ObjectDescriptor +>ObjectDescriptor : ObjectDescriptor +>D : D +>M : M +>D : D +>M : M + +let x1 = makeObject({ +>x1 : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>makeObject({ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } }}) : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>makeObject : (desc: ObjectDescriptor) => D & M +>{ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } }} : { data: { x: number; y: number; }; methods: { moveBy(dx: number, dy: number): void; }; } + + data: { x: 0, y: 0 }, +>data : { x: number; y: number; } +>{ x: 0, y: 0 } : { x: number; y: number; } +>x : number +>0 : 0 +>y : number +>0 : 0 + + methods: { +>methods : { moveBy(dx: number, dy: number): void; } +>{ moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } } : { moveBy(dx: number, dy: number): void; } + + moveBy(dx: number, dy: number) { +>moveBy : (dx: number, dy: number) => void +>dx : number +>dy : number + + this.x += dx; // Strongly typed this +>this.x += dx : number +>this.x : number +>this : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>x : number +>dx : number + + this.y += dy; // Strongly typed this +>this.y += dy : number +>this.y : number +>this : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>y : number +>dy : number + } + } +}); + +// In methods contained in an object literal with a contextual type that includes +// some ThisType, 'this' is of type T. + +type ObjectDescriptor2 = ThisType & { +>ObjectDescriptor2 : ObjectDescriptor2 +>D : D +>M : M +>ThisType : ThisType +>D : D +>M : M + + data?: D; +>data : D +>D : D + + methods?: M; +>methods : M +>M : M +} + +declare function makeObject2(desc: ObjectDescriptor): D & M; +>makeObject2 : (desc: ObjectDescriptor) => D & M +>D : D +>M : M +>desc : ObjectDescriptor +>ObjectDescriptor : ObjectDescriptor +>D : D +>M : M +>D : D +>M : M + +let x2 = makeObject2({ +>x2 : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>makeObject2({ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } }}) : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>makeObject2 : (desc: ObjectDescriptor) => D & M +>{ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } }} : { data: { x: number; y: number; }; methods: { moveBy(dx: number, dy: number): void; }; } + + data: { x: 0, y: 0 }, +>data : { x: number; y: number; } +>{ x: 0, y: 0 } : { x: number; y: number; } +>x : number +>0 : 0 +>y : number +>0 : 0 + + methods: { +>methods : { moveBy(dx: number, dy: number): void; } +>{ moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } } : { moveBy(dx: number, dy: number): void; } + + moveBy(dx: number, dy: number) { +>moveBy : (dx: number, dy: number) => void +>dx : number +>dy : number + + this.x += dx; // Strongly typed this +>this.x += dx : number +>this.x : number +>this : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>x : number +>dx : number + + this.y += dy; // Strongly typed this +>this.y += dy : number +>this.y : number +>this : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>y : number +>dy : number + } + } +}); + +// Proof of concept for typing of Vue.js + +type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; +>Accessors : Accessors +>T : T +>K : K +>T : T +>T : T +>K : K +>Computed : Computed +>T : T +>K : K + +type Dictionary = { [x: string]: T } +>Dictionary : Dictionary +>T : T +>x : string +>T : T + +type Computed = { +>Computed : Computed +>T : T + + get?(): T; +>get : () => T +>T : T + + set?(value: T): void; +>set : (value: T) => void +>value : T +>T : T +} + +type VueOptions = ThisType & { +>VueOptions : VueOptions +>D : D +>M : M +>P : P +>ThisType : ThisType +>D : D +>M : M +>P : P + + data?: D | (() => D); +>data : D | (() => D) +>D : D +>D : D + + methods?: M; +>methods : M +>M : M + + computed?: Accessors

; +>computed : Accessors

+>Accessors : Accessors +>P : P +} + +declare const Vue: new (options: VueOptions) => D & M & P; +>Vue : new (options: VueOptions) => D & M & P +>D : D +>M : M +>P : P +>options : VueOptions +>VueOptions : VueOptions +>D : D +>M : M +>P : P +>D : D +>M : M +>P : P + +let vue = new Vue({ +>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>new Vue({ data: () => ({ x: 1, y: 2 }), methods: { f(x: string) { return this.x; } }, computed: { test(): number { return this.x; }, hello: { get() { return "hi"; }, set(value: string) { } } }}) : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>Vue : new (options: VueOptions) => D & M & P +>{ data: () => ({ x: 1, y: 2 }), methods: { f(x: string) { return this.x; } }, computed: { test(): number { return this.x; }, hello: { get() { return "hi"; }, set(value: string) { } } }} : { data: () => { x: number; y: number; }; methods: { f(x: string): number; }; computed: { test(): number; hello: { get(): string; set(value: string): void; }; }; } + + data: () => ({ x: 1, y: 2 }), +>data : () => { x: number; y: number; } +>() => ({ x: 1, y: 2 }) : () => { x: number; y: number; } +>({ x: 1, y: 2 }) : { x: number; y: number; } +>{ x: 1, y: 2 } : { x: number; y: number; } +>x : number +>1 : 1 +>y : number +>2 : 2 + + methods: { +>methods : { f(x: string): number; } +>{ f(x: string) { return this.x; } } : { f(x: string): number; } + + f(x: string) { +>f : (x: string) => number +>x : string + + return this.x; +>this.x : number +>this : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>x : number + } + }, + computed: { +>computed : { test(): number; hello: { get(): string; set(value: string): void; }; } +>{ test(): number { return this.x; }, hello: { get() { return "hi"; }, set(value: string) { } } } : { test(): number; hello: { get(): string; set(value: string): void; }; } + + test(): number { +>test : () => number + + return this.x; +>this.x : number +>this : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>x : number + + }, + hello: { +>hello : { get(): string; set(value: string): void; } +>{ get() { return "hi"; }, set(value: string) { } } : { get(): string; set(value: string): void; } + + get() { +>get : () => string + + return "hi"; +>"hi" : "hi" + + }, + set(value: string) { +>set : (value: string) => void +>value : string + } + } + } +}); + +vue; +>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } + +vue.x; +>vue.x : number +>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>x : number + +vue.f("abc"); +>vue.f("abc") : number +>vue.f : (x: string) => number +>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>f : (x: string) => number +>"abc" : "abc" + +vue.test; +>vue.test : number +>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>test : number + +vue.hello; +>vue.hello : string +>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>hello : string + diff --git a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts new file mode 100644 index 00000000000..7358b47259c --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts @@ -0,0 +1,144 @@ +// @declaration: true +// @noImplicitAny: true +// @noImplicitThis: true +// @target: es5 + +// In methods of an object literal with no contextual type, 'this' has the type +// of the object literal. + +let obj1 = { + a: 1, + f() { + return this.a; + }, + b: "hello", + c: { + g() { + this.g(); + } + }, + get d() { + return this.a; + }, + get e() { + return this.b; + }, + set e(value) { + this.b = value; + } +}; + +// In methods of an object literal with a contextual type, 'this' has the +// contextual type. + +type Point = { + x: number; + y: number; + moveBy(dx: number, dy: number): void; +} + +let p1: Point = { + x: 10, + y: 20, + moveBy(dx, dy) { + this.x += dx; + this.y += dy; + } +}; + +declare function f1(p: Point): void; + +f1({ + x: 10, + y: 20, + moveBy(dx, dy) { + this.x += dx; + this.y += dy; + } +}); + +// In methods of an object literal with a contextual type that includes some +// ThisType, 'this' is of type T. + +type ObjectDescriptor = { + data?: D; + methods?: M & ThisType; // Type of 'this' in methods is D & M +} + +declare function makeObject(desc: ObjectDescriptor): D & M; + +let x1 = makeObject({ + data: { x: 0, y: 0 }, + methods: { + moveBy(dx: number, dy: number) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + } + } +}); + +// In methods contained in an object literal with a contextual type that includes +// some ThisType, 'this' is of type T. + +type ObjectDescriptor2 = ThisType & { + data?: D; + methods?: M; +} + +declare function makeObject2(desc: ObjectDescriptor): D & M; + +let x2 = makeObject2({ + data: { x: 0, y: 0 }, + methods: { + moveBy(dx: number, dy: number) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + } + } +}); + +// Proof of concept for typing of Vue.js + +type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; + +type Dictionary = { [x: string]: T } + +type Computed = { + get?(): T; + set?(value: T): void; +} + +type VueOptions = ThisType & { + data?: D | (() => D); + methods?: M; + computed?: Accessors

; +} + +declare const Vue: new (options: VueOptions) => D & M & P; + +let vue = new Vue({ + data: () => ({ x: 1, y: 2 }), + methods: { + f(x: string) { + return this.x; + } + }, + computed: { + test(): number { + return this.x; + }, + hello: { + get() { + return "hi"; + }, + set(value: string) { + } + } + } +}); + +vue; +vue.x; +vue.f("abc"); +vue.test; +vue.hello;